Using Go on OpenWRT / MIPS architecture ?

6,558 views
Skip to first unread message

Shazz

unread,
Apr 10, 2012, 5:14:24 AM4/10/12
to golang-dev
Hello,

Sorry for any dumb question, I'm learning Go !
So I plan to code some little stuff it on a embedded device (little 3G
Wifi router (http://wiki.openwrt.org/toh/tp-link/tl-mr3020)) but I
guess it is required to be bale to compile the Go code for the
targetted CPU / env (MIPS 24Kc / OpenWRT linux).
I understood that it is possible to compile Go code using the cgo
compilers (for x86, ARM and AMD64) but also using a gcc frontend :
gccgo

Does it mean that if I can recompile gcc for OpenWRT using the gccgo
frontend, it will be able to compile my code ? Is it a naive view and
a mountain is hidden behind the fog ?

Thanks in advance,

shazz

minux

unread,
Apr 10, 2012, 11:08:26 AM4/10/12
to Shazz, golang-dev
For mips target, you can only use gccgo to compile Go code.

Ian Lance Taylor

unread,
Apr 11, 2012, 1:17:44 AM4/11/12
to Shazz, golang-dev
Shazz <sha...@gmail.com> writes:

I don't know if anybody has tried gccgo on a MIPS GNU/Linux target, but
I don't know of any reason why it would not work. Gccgo has been used
successfully on MIPS Irix targets.

Ian

Ian Lance Taylor

unread,
Aug 17, 2012, 6:56:59 PM8/17/12
to sha...@gmail.com, golan...@googlegroups.com, kro...@gmail.com
On Fri, Aug 17, 2012 at 2:39 PM, <sha...@gmail.com> wrote:
>
> So I succeded in compiling gccgo for openwrt (if you'll like to know how
> email me, quite simple after all) but the linker fails :
>
> $ mips-openwrt-linux-gccgo hello.go
> /var/www/LOG/openwrt/toolchain/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_eglibc-2.15/lib/gcc/mips-openwrt-linux-gnu/4.7.1/../../../../mips-openwrt-linux-gnu/bin/ld:
> skipping incompatible /usr/lib/libm.so when searching for -lm
> /var/www/LOG/openwrt/toolchain/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_eglibc-2.15/lib/gcc/mips-openwrt-linux-gnu/4.7.1/../../../../mips-openwrt-linux-gnu/bin/ld:
> skipping incompatible /usr/lib/libm.a when searching for -lm
> /var/www/LOG/openwrt/toolchain/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_eglibc-2.15/lib/gcc/mips-openwrt-linux-gnu/4.7.1/../../../../mips-openwrt-linux-gnu/bin/ld:
> skipping incompatible /usr/lib/libc.so when searching for -lc
> /var/www/LOG/openwrt/toolchain/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_eglibc-2.15/lib/gcc/mips-openwrt-linux-gnu/4.7.1/../../../../mips-openwrt-linux-gnu/bin/ld:
> skipping incompatible /usr/lib/libc.a when searching for -lc
> /var/www/LOG/openwrt/toolchain/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_eglibc-2.15/lib/gcc/mips-openwrt-linux-gnu/4.7.1/../../../../mips-openwrt-linux-gnu/bin/ld:
> skipping incompatible /usr/lib/libc_nonshared.a when searching for
> libc_nonshared.a
>
> so instead of looking in
> /var/www/LOG/openwrt/toolchain/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_eglibc-2.15/lib,
> ld looks in /usr/libwhich is obviously not a mips library...
>
> I tried to set LD_LIBRAY_PATH, add -Wl to gvvgo but same result, any idea ?

LD_LIBRARY_PATH is for the dynamic linker, not the program linker.
What you need for the program linker is some -L options, or set the
environment variable LIBRARY_PATH.

However, it's quite odd that the cross-linker is looking in /usr/lib
at all. Cross-linkers normally do not do that. That suggests that
something has been misconfigured. If you pass -v to gccgo you will
see exactly how it is invoking the linker.

Ian

Shazz/MJJ Pr0d^TRSI

unread,
Aug 19, 2012, 7:19:45 AM8/19/12
to Ian Lance Taylor, golan...@googlegroups.com, kro...@gmail.com
Thanks Ian,

Works perfectly with the -L flag.
I agree quite odd to look into /usr/lib... do you know where this is set while building the toolchain  ? Is the configure options ?

Btw, that's cool now I can test go on embedded devices !

And first issues came out ...
I just recompiled the samples (hello world, pi, solitaire, fib,..) and ran them and it seems I've got memory issues (remember my devices hve only 32Mbytes of RAM and a few left...)
- hello : ok
- fib : ok
- peano : KO (segfault)
0 ! = 1
1 ! = 1
2 ! = 2
3 ! = 6
4 ! = 24
5 ! = 120
6 ! = 720
7 ! = 5040
8 ! = 40320
Segmentation fault

- pi : KO :
runtime: memory allocated by OS (0x36b00000) not in usable range [0x57038000,0xd7038000)
runtime: out of memory: cannot allocate 2097152-byte block (535822336 in use)
throw: out of memory

- tree : ok
- sieve : ok
- solitaire : ok
- http (from gotour) : segfault on first http client connection

How can I get more info on the segfault on the device ?
And for PI's memory issues, I'll try to reduce the number of concurrent processes :)

Ian Lance Taylor

unread,
Aug 19, 2012, 2:19:11 PM8/19/12
to Shazz/MJJ Pr0d^TRSI, golan...@googlegroups.com, kro...@gmail.com
On Sun, Aug 19, 2012 at 4:19 AM, Shazz/MJJ Pr0d^TRSI <sha...@gmail.com> wrote:
>
> I agree quite odd to look into /usr/lib... do you know where this is set
> while building the toolchain ? Is the configure options ?

There are a couple of places that it could come from. I suppose the
most likely is the default linker script. Try doing a link with
-Wl,--verbose and look for a SEARCH_DIRS line.

> And first issues came out ...
> I just recompiled the samples (hello world, pi, solitaire, fib,..) and ran
> them and it seems I've got memory issues (remember my devices hve only
> 32Mbytes of RAM and a few left...)
> - hello : ok
> - fib : ok
> - peano : KO (segfault)
> 0 ! = 1
> 1 ! = 1
> 2 ! = 2
> 3 ! = 6
> 4 ! = 24
> 5 ! = 120
> 6 ! = 720
> 7 ! = 5040
> 8 ! = 40320
> Segmentation fault

The peano test uses a great deal of stack space. I wouldn't worry
about this failure.

> - pi : KO :
> runtime: memory allocated by OS (0x36b00000) not in usable range
> [0x57038000,0xd7038000)
> runtime: out of memory: cannot allocate 2097152-byte block (535822336 in
> use)
> throw: out of memory

Not sure what this is--is this more output from the peano failure?
There is a pidigits test but there is no pi test.

> - http (from gotour) : segfault on first http client connection
>
> How can I get more info on the segfault on the device ?

You ought to get a stack trace on a segfault. I don't know why you
are not getting one. Perhaps that is the first place to look.

Ian

Ian Lance Taylor

unread,
Aug 20, 2012, 11:02:44 AM8/20/12
to Shazz/MJJ Pr0d^TRSI, golan...@googlegroups.com, kro...@gmail.com
On Mon, Aug 20, 2012 at 7:40 AM, Shazz/MJJ Pr0d^TRSI <sha...@gmail.com> wrote:
>
> About the little gotour http test :
>>
>> package main
>> import (
>> "fmt"
>> "net/http"
>> )
>> type Hello struct{}
>> func (h Hello) ServeHTTP(
>> w http.ResponseWriter,
>> r *http.Request) {
>> fmt.Fprint(w, "Hello!")
>> }
>> func main() {
>> var h Hello
>> http.ListenAndServe("localhost:4000",h)
>> }
>
>
> When I run it, the process waits (normal behavior) and as soon as I wget (or
> open a brower), segfault, nothing else.
> What can I do to get the stacktrace ?

You shouldn't need to add anything. It should happen by default. The
relevant code is in libgo/runtime/go-signal.c. If nothing else, you
should get the address where the segmentation fault occurred. You
didn't show the exact printout from running the program, so I'm not
sure exactly what you are seeing.


> Then I tried to recompile gccgo using the "default" openwrt libc library,
> uclibc instead og eglibc, but gccgo doesn't compile because it require
> set/make/context routines which are not implemented by uclibc..
> ...so stucked with eglibc (and a bigger footprint)
> toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:
> In function '__go_go':
> toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:1368:2:
> error: implicit declaration of function 'makecontext'
> [-Werror=implicit-function-declaration]
>
> So not so easy to run Go on embedded devices :(

The getcontext/savecontext/makecontext routines are small and you
could port them. But it would of course be non-trivial.

Ian

Shazz/MJJ Pr0d^TRSI

unread,
Aug 20, 2012, 10:40:03 AM8/20/12
to Ian Lance Taylor, golan...@googlegroups.com, kro...@gmail.com
Thanks Ian.
I'll test the linker tonight.

About the segfaults issues, so for the pi code, that's ok, if I reduce the number of go routines, it doesn't crash, by default 5000 was too much :)
func main() {
fmt.Println(pi(5000))
}
// pi launches n goroutines to compute an
// approximation of pi.
func pi(n int) float64 {

About the little gotour http test : 
package main
import (
"fmt"
"net/http"
)
type Hello struct{}
func (h Hello) ServeHTTP(
w http.ResponseWriter,
r *http.Request) {
fmt.Fprint(w, "Hello!")
}
func main() {
var h Hello
http.ListenAndServe("localhost:4000",h)
}

When I run it, the process waits (normal behavior) and as soon as I wget (or open a brower), segfault, nothing else.
What can I do to get the stacktrace ? Is there any code I can add to the example ? Exception handler ?
Something like :
err := http.ListenAndServe(":4000", h)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
?

I tried to run it from gdb but there is not enough memory for gdb.... sigh...

Then I tried to recompile gccgo using the "default" openwrt libc library, uclibc instead og eglibc, but gccgo doesn't compile because it require set/make/context routines which are not implemented by uclibc..
...so stucked with eglibc (and a bigger footprint)
toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c: In function '__go_go':
toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:1368:2: error: implicit declaration of function 'makecontext' [-Werror=implicit-function-declaration]

So not so easy to run Go on embedded devices :(


--
Shazz / TRSi ^ MJJ Prod
http://www.trsi.de/users/shazz/

Shazz/MJJ Pr0d^TRSI

unread,
Aug 20, 2012, 11:13:14 AM8/20/12
to Ian Lance Taylor, golan...@googlegroups.com
I'll take a look at what the getcontext/savecontext/makecontext routines should look like... I hope it's not processor specific.

Concerning the http example segfault that's easy, no stacktrace just :
$./http
Segmentation fault 

exactly like the peano output I sent a few emails ago, nothing else than "Segmentation fault", no address, nothing, void.

I understand it is not a normal behavior...

minux

unread,
Aug 20, 2012, 11:17:27 AM8/20/12
to golang-dev, Ian Lance Taylor, kro...@gmail.com

On Mon, Aug 20, 2012 at 10:40 PM, Shazz/MJJ Pr0d^TRSI <sha...@gmail.com> wrote:
I tried to run it from gdb but there is not enough memory for gdb.... sigh...
can you strace it? at least you can know the pc and signal name.
if not enough memory for a native gdb, you can use gdbserver, which requires little memory
to run.

Then I tried to recompile gccgo using the "default" openwrt libc library, uclibc instead og eglibc, but gccgo doesn't compile because it require set/make/context routines which are not implemented by uclibc..
...so stucked with eglibc (and a bigger footprint)
toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c: In function '__go_go':
toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:1368:2: error: implicit declaration of function 'makecontext' [-Werror=implicit-function-declaration]
i've heard someone on this list has ported the these context routines to uclibc for ARM, so
i think you could do the same for MIPS; should not be difficult.
So not so easy to run Go on embedded devices :(
Run Go on ARM is pretty easy because gc supports it :-)
it's very unfortunate gc doesn't support MIPS or PowerPC, which are used in lots of embedded
systems (i want to use Go on my router, so I have to either choose an ARM-based solution or
get around the uclibc problem).

@iant, does gccgo accept archiecture specific code (e.g. context switch code for uclibc) so that
it could support uclibc?

minux

unread,
Aug 20, 2012, 11:23:10 AM8/20/12
to Shazz/MJJ Pr0d^TRSI, Ian Lance Taylor, golan...@googlegroups.com
On Mon, Aug 20, 2012 at 11:13 PM, Shazz/MJJ Pr0d^TRSI <sha...@gmail.com> wrote:
I'll take a look at what the getcontext/savecontext/makecontext routines should look like... I hope it's not processor specific.
some of them are architecture specific (e.g. coded in assembly), but it not complex, just
save and restoring a couple of registers.

Concerning the http example segfault that's easy, no stacktrace just :
$./http
Segmentation fault 

exactly like the peano output I sent a few emails ago, nothing else than "Segmentation fault", no address, nothing, void.
i think the first step would be using strace to get the faulting pc, and use addr2line to get the offending line.

if it doesn't help, try build a cross gdb and use gdbserver.

Shazz/MJJ Pr0d^TRSI

unread,
Aug 20, 2012, 11:34:35 AM8/20/12
to minux, golang-dev
Hello Minux,

I'll printout tonight the gdb errors but basically it says it cannot allocate 3Mb of RAM to do some stuff as soon as I ask him to start my go program.
I never used gdbserver, how does it work in a few words or in other words, what should I compile on my openwrt router ?

Yep I found this message :  http://www.mail-archive.com/ucl...@uclibc.org/msg08376.html, I emailed the guy... I wait now :) But it seems he had some issues.
Using eglibc (hidden option of openwrt), it solves the issue but so few RAM left... I have to learn how to squeeze eglibc footprint...(e.g. remove useless features)

Btw I'll take a look at common xContext routines, maybe from eglibc..

whatever thx for the reply :)

Shazz/MJJ Pr0d^TRSI

unread,
Aug 20, 2012, 11:55:23 AM8/20/12
to minux, Ian Lance Taylor, golan...@googlegroups.com
I found that... maybe it can be ported "as is" as it doesn't look to be dependent of any eglibc stuff

Ian Lance Taylor

unread,
Aug 20, 2012, 11:58:23 AM8/20/12
to Shazz/MJJ Pr0d^TRSI, golan...@googlegroups.com
On Mon, Aug 20, 2012 at 8:13 AM, Shazz/MJJ Pr0d^TRSI <sha...@gmail.com> wrote:
> I'll take a look at what the getcontext/savecontext/makecontext routines
> should look like... I hope it's not processor specific.

It's entirely processor specific, sorry. But it's library-independent.


> Concerning the http example segfault that's easy, no stacktrace just :
> $./http
> Segmentation fault
>
> exactly like the peano output I sent a few emails ago, nothing else than
> "Segmentation fault", no address, nothing, void.
>
> I understand it is not a normal behavior...

That sounds like the SIGSEGV handler was not installed for some
reason. I have no explanation for that. It should be set up by
runtime_initsig in libgo/runtime/signal_unix.c.

minux

unread,
Aug 20, 2012, 11:58:21 AM8/20/12
to Shazz/MJJ Pr0d^TRSI, golang-dev
On Mon, Aug 20, 2012 at 11:34 PM, Shazz/MJJ Pr0d^TRSI <sha...@gmail.com> wrote:
I'll printout tonight the gdb errors but basically it says it cannot allocate 3Mb of RAM to do some stuff as soon as I ask him to start my go program.
I never used gdbserver, how does it work in a few words or in other words, what should I compile on my openwrt router ?
gdbserver will require much less memory to run.
it is basically the process control part of gdb, and you can run gdb-mips on your PC, and have it talk to
gdbserver to control the process under debugging.

openwrt has a wiki article explaining what you need to do to use gdbserver:

Yep I found this message :  http://www.mail-archive.com/ucl...@uclibc.org/msg08376.html, I emailed the guy... I wait now :) But it seems he had some issues.
Using eglibc (hidden option of openwrt), it solves the issue but so few RAM left... I have to learn how to squeeze eglibc footprint...(e.g. remove useless features)
you could try shrinking eglibc, but i'm afraid it probably will never be as small as uclibc.

Ian Lance Taylor

unread,
Aug 20, 2012, 12:00:07 PM8/20/12
to minux, golang-dev, kro...@gmail.com
On Mon, Aug 20, 2012 at 8:17 AM, minux <minu...@gmail.com> wrote:
>
> @iant, does gccgo accept archiecture specific code (e.g. context switch code
> for uclibc) so that
> it could support uclibc?

Sure, the libgo Makefile can do approximately anything.

In fact I do want to add processor-specific context switching code at
some point, as getcontext and setcontext set the signal masks, which
is not necessary for Go.

Ian

minux

unread,
Oct 7, 2012, 1:33:45 AM10/7/12
to jobs....@gmail.com, golan...@googlegroups.com, Shazz, kro...@gmail.com

On Sun, Oct 7, 2012 at 7:09 AM, <jobs....@gmail.com> wrote:

How to get "mips-openwrt-linux-gccgo"? 
You need to build it by yourself.
Just apply normal cross compiling options to binutils/gcc configure script
(e.g. --target)

Shazz/MJJ Pr0d^TRSI

unread,
Oct 19, 2012, 10:08:39 AM10/19/12
to jobs....@gmail.com, golan...@googlegroups.com, kro...@gmail.com
You need to use EGLIBC (developper options) as it requires some stuff not ported in UCLIBC

On Tue, Oct 9, 2012 at 5:24 AM, <jobs....@gmail.com> wrote:
Thanks  minux .

 I found a simple method:
   1.    vim toolchain/common.mk
          update  TARGET_LANGUAGES, add "CONFIG_INSTALL_GCCGO"
             SEP:=,
            TARGET_LANGUAGES:="c$(if $(CONFIG_INSTALL_LIBSTDCPP),$(SEP)c++)$(if $(CONFIG_INSTALL_LIBGCJ),$(SEP)java)$(if                      $(CONFIG_INSTALL_GFORTRAN),$(SEP)fortran)$(if $(CONFIG_INSTALL_GCCGO),$(SEP)go)"

2.     vim toolchain/Config.in
        add :
            config INSTALL_GCCGO
        bool
        prompt "Build/install gccgo compiler?" if TOOLCHAINOPTS
        default n
        help
            Build/install GNU gccgo compiler ?

3.    make menuconfig    (select gccgo in toolchain)

4.    make V=99

5.  .....
     .....   
  /home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c: In function 'runtime_gogo':
/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:300:2: error: implicit declaration of function 'setcontext' [-Werror=implicit-function-declaration]
/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c: In function 'runtime_mcall':
/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:335:3: error: implicit declaration of function 'getcontext' [-Werror=implicit-function-declaration]
/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c: In function '__go_go':
/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04/libgo/runtime/proc.c:1368:2: error: implicit declaration of function 'makecontext' [-Werror=implicit-function-declaration]
cc1: all warnings being treated as errors
make[8]: *** [proc.lo] Error 1
make[8]: Leaving directory `/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04-final/mips-openwrt-linux-uclibc/libgo'
make[7]: *** [all-recursive] Error 1
make[7]: Leaving directory `/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04-final/mips-openwrt-linux-uclibc/libgo'
make[6]: *** [all] Error 2
make[6]: Leaving directory `/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04-final/mips-openwrt-linux-uclibc/libgo'
make[5]: *** [all-target-libgo] Error 2
make[5]: Leaving directory `/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04-final'
make[4]: *** [all] Error 2
make[4]: Leaving directory `/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04-final'
make[3]: *** [/home/justin/OpenWRT/trunk/build_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/gcc-linaro-4.7-2012.04-final/.built] Error 2
make[3]: Leaving directory `/home/justin/OpenWRT/trunk/toolchain/gcc/final'
make[2]: *** [toolchain/gcc/final/compile] Error 2
make[2]: Leaving directory `/home/justin/OpenWRT/trunk'
make[1]: *** [/home/justin/OpenWRT/trunk/staging_dir/toolchain-mips_r2_gcc-4.7-linaro_uClibc-0.9.33.2/stamp/.toolchain_install] Error 2
make[1]: Leaving directory `/home/justin/OpenWRT/trunk'
make: *** [world]  Error  2

   


minux於 2012年10月7日星期日UTC+8下午1時34分07秒寫道:

gjr1...@gmail.com

unread,
Feb 4, 2014, 8:03:38 AM2/4/14
to golan...@googlegroups.com
Hi,

I have made patches for openwrt to create the gccgo compiler for mips.
http://patchwork.openwrt.org/patch/4711/

Patch can be viewed here:
https://github.com/GeertJohan/openwrt-go/compare/add-gccgo-and-libgo

/GeertJohan
Reply all
Reply to author
Forward
0 new messages