1

I am trying to compile compile a simple "hello world" program for an Axis A210 (cris architecture). I managed to get download GCC from the vendor, but it came with glibc, and the camera is running uClibc-0.9.27. I pulled the file /lib/libuClibc-0.9.27.so from the device.

I managed to compile this program that segfaults:

#include <unistd.h>

int main(int argc, char** argv)
{
    *((unsigned int*)0) = 0xDEAD;
}

and this program that just hangs:

#include <unistd.h>

int main(int argc, char** argv)
{
    int a = 0;
}

with cris-gcc -g -static -nostdlib -o compiled main.c.

Now I'd like to use the functions in libuClibc, but I can't seem to get the linking to work: I've tried

cris-gcc -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.

but that just gives:

./libuClibc-0.9.27.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status

Is there a way to link to this .so file or to otherwise get some standard functions like exit working?

redfast00
  • 1,363
  • 1
  • 12
  • 23
  • 2
    You also need to use a cross linker. You can supply path to the linker to `gcc` via the `-B` option. Check which linker executable is used with `gcc -v` or `strace` (IIRC, the former fails to output `ld` invocation -- but it does output the invocation of `collect2`, which is a thin wrapper for `ld`). – Vladislav Ivanishin Jun 23 '19 at 15:59
  • @VladislavIvanishin I think it's using the correct linker (but I'm not sure): the output of `strace` shows `stat64("/usr/local/cris/lib/gcc-lib/cris-axis-elf/3.2.1/collect2", {st_mode=S_IFREG|0755, st_size=85464, ...}) = 0`, which I think is the correct path – redfast00 Jun 23 '19 at 16:11
  • It is not clear yet. That's only the path to the `collect2` wrapper, which ships with the compiler. It then should call the linker (most likely, `ld`, or `ld.bfd` mb also suffixed with something) which is shipped separately, with the binutils package. – Vladislav Ivanishin Jun 23 '19 at 16:17
  • @VladislavIvanishin there does seem to be something wrong with the linking step: after running `cris-gcc -g -static -nostdlib -o compiled.o main.c -c`, I ran `cris-ld -o linked compiled.o libuClibc-0.9.27.so` and that gives the same error. – redfast00 Jun 23 '19 at 16:24
  • 1
    Are `cris-nm`, `cris-objdump`, or `cris-readelf` able to read symbols from `libuClibc-0.9.27.so`? – Vladislav Ivanishin Jun 23 '19 at 16:31
  • Also, you can try the Gold linker: `gcc -fuse-ld=gold` (or just invoke it directly as `ld.gold`). Error messages produced by Gold are often more descriptive. – Vladislav Ivanishin Jun 23 '19 at 16:38
  • Have you considering rebuilding your GCC from the FSF source code of GCC? – Basile Starynkevitch Jun 23 '19 at 16:44
  • @VladislavIvanishin hmm, `cris-nm` says there are no symbols, but the output of `readelf -Wa ` is longer and does seem to contain function names (https://termbin.com/w76a). The `file` command does say the library was stripped, don't know if that helps? – redfast00 Jun 23 '19 at 17:04
  • @VladislavIvanishin I don't have the gold linker for cris unfortunately – redfast00 Jun 23 '19 at 17:05
  • @BasileStarynkevitch I'd really like to avoid that, but will do that if nothing else works – redfast00 Jun 23 '19 at 17:05
  • OK, the library was stripped, therefore nm w/o the `-D` option gives nothing (there's no regular symbol table, only `.dynsym`). No surprises here. Now, at this point I would debug the linker (grep for the error message, the origin seems quite localized) or just report this issue to the binutils BZ­. The first thing I would do anyway is build the newest versions of the two GNU linkers and see if the issue is reproducible. I don't see a point in building GCC, as you don't recompile the library. – Vladislav Ivanishin Jun 23 '19 at 18:06
  • Sorry, of course this issue should not be reported upstream if CRIS is not an architecture currently supported by GNU binutils. That leaves you with the option of contacting the vendor or debugging it yourself. – Vladislav Ivanishin Jun 23 '19 at 18:21
  • @VladislavIvanishin I just built binutils 2.28 for CRIS (target=cris-elf), and then tried both linkers (cris-elf-ld.bfd and cris-elf-ld). This works for the compiled binary without the library (`-o compiled compiled.o`), but gives `error adding symbols: File in wrong format` for `-o compiled compiled.o -luClibc-0.9.27 -L.`. I don't know why, because the `file` command does say it's a `libuClibc-0.9.27.so: ELF 32-bit LSB shared object, Axis cris, version 1 (SYSV), dynamically linked, interpreter /lib, stripped`. I'm now building the latest version from git to see if that changes things, maybe? – redfast00 Jun 23 '19 at 18:35
  • It might be that the target is not precise enough. It's an ELF32 for Axis cris alright, but maybe some bits are still different for your binutils and the library.. Try linking a dummy library and comparing the outputs of `file`, `readelf`, maybe even `hexdump`. Or since you've already built binutils, just debug the linker to see why exaclty it thinks there's a problem with the fomat. – Vladislav Ivanishin Jun 23 '19 at 18:59
  • the second posted program does not 'hang'. Rather is runs to completion, (which does nothing) then exits. – user3629249 Jun 24 '19 at 14:02
  • @user3629249 That's indeed what it *should* do, but it doesn't actually exit though, I don't know why. I can't debug it either, because the camera doesn't have gdb on it. – redfast00 Jun 24 '19 at 15:15

2 Answers2

0

regarding:

cris-gcc -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.

The linker works with libraries in the order they are encountered. So they must be listed in the order needed.

The linker needs to know where the library is located before knowing which library to examine. Suggest:

cris-gcc -g -static -nostdlib -o compiled main.c -L.  -luClibc-0.9.27 

However, a *.so library is NOT a static library. It is a dynamic library, so the option: -static should be removed However, that requires that the dynamic library be available at 'run time' if the related *.a (a static library) is available then it should be used in the compile/link statement.

Note: the function: exit() has its' prototype exposed via the stdlib.h header file, not the unistd.h header file.

regarding:

#include <unistd.h>

int main(int argc, char** argv)
{
    *((unsigned int*)0) = 0xDEAD;
}

the parameters: argc and argv are not used, so the compiler will output two warning statements about 'unused parameters'. Suggest using the function signature: int main( void )

this code is trying to write to address 0. However, the application does not 'own' address 0, (an usually, such an address will be 'marked' as 'readonly' so the application will exit with a 'seg fault event')

it is poor programming practice to include header files those contents are not used. Suggest removing the statement: #include <unistd.h>

this statement: int a = 0; will result in the compiler outputting a warning message about a variable that is 'set' but never 'used'

regarding:

cris-gcc -g -static -nostdlib -o compiled main.c -L. -luClibc-0.9.27

When compiling, should always enable the warnings, then fix those warnings. Suggest:

cris-gcc -Wall -Wextra -Wconversion -pedantic -std=c99 -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.    
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • That doesn't answer my question though: these are a whole bunch of good practices. I know my code is bad, but I just want it to compile, and it still gives the same error when I execute `cris-gcc -nostdlib -o compiled main.c -L. -luClibc-0.9.27`: ``` ./libuClibc-0.9.27.so: could not read symbols: Invalid operation collect2: ld returned 1 exit status ``` – redfast00 Jun 23 '19 at 15:43
  • Then, does the library reside in the same directory as where the source code resides and the compile-link operations are being performed? – user3629249 Jun 23 '19 at 22:19
  • Yes, it does, also see the comments on the question. My current theory is that the architecture of the library might be subtly different from what the compiler produces, but I'm not sure how to debug that. – redfast00 Jun 24 '19 at 11:06
  • @user3629249, position 0 is normally marked not accessable (even for reading).... so dereferences of the `NULL` pointer always result in a `SIGSEGV`, not readable as you say. – Luis Colorado Jun 25 '19 at 07:19
0

Apart of all the problems noticed by @user3629249 in his answer (all of them are to be followed), the message:

./libuClibc-0.9.27.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status

means that the libuClibc-0.9.27.so binary has been stripped its symbols or you have not privileges to read the file, and so, the symbol table. The linker is unable to use that binary and it can only be loaded into memory. Anyway, you need a nonstripped shared object, and as suggested by @user3629249, don't use -static (by the reason stated in his answer), put the parameters in order (library dir before the library to be linked, also stated by him). Even you can link the shared by specifying it as:

cris-gcc -nostdlib -o compiled main.c libluClibc-0.9.27.so

and another thing: You need not only the standard C library to link an executable... you normally use a crt0.o at the beginning of your program with the C runtime and the start code for your program. You have not included that, and probably the compiler is getting it from another place.

One question: If you got the compiler, why do you intend to supply your own version of the standard library? isn't provided by the compiler? If you change the libc, then you must change also the crt0.o file. It defaults to some compiler provided, and you haven't received the message no definition for start.

Try to compile with just a main function, as you did, but don't specify shared libraries or directories... just the main code:

cris-gcc -o compiled main.c

and see what happens.... this will be very illustrative of what you lack in your system.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31