Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

find_linux_crt_begin returns wrong path #1734

Open
matteac opened this issue Dec 28, 2024 · 4 comments
Open

find_linux_crt_begin returns wrong path #1734

matteac opened this issue Dec 28, 2024 · 4 comments
Labels
Enhancement Request New feature or request Help Wanted! Community help would be great!

Comments

@matteac
Copy link

matteac commented Dec 28, 2024

The function find_linux_crt_begin returns an incorrect path if there are multiple GCC installations with alphabetically preceding names on the system

Host:

  • x86_64-pc-linux-gnu

Installed GCC:

  • aarch64-linux-gnu
  • x86_64-pc-linux-gnu

The function returns the path to the crtbegin inside aarch64-linux-gnu instead of the path for the host architecture (x86_64-pc-linux-gnu) or the target specified in project.json

Steps to Reproduce

$ c3c init dyn_lib --template dynamic_lib
$ cd dyn_lib
$ c3c build

Log:

ld.lld: error: /usr/lib/gcc/aarch64-linux-gnu/14.2.0/crtbeginS.o is incompatible with elf64-x86-64
ld.lld: error: /usr/lib/gcc/aarch64-linux-gnu/14.2.0/crtendS.o is incompatible with elf64-x86-64
Failed to create a dynamic library: (null)

This happens even with the target specified in project.json

The problem itself is in the function find_arch_glob_path that returns the first path that matches the pattern /usr/lib/gcc/*/*/crtbegin.o

This doesn't happen if you specify the path with --linux-crtbegin, but I assume that's not the expected behaviour

@lerno
Copy link
Collaborator

lerno commented Dec 29, 2024

It will pick the first match. Given the amount of different setups on Linux, there is no way to know what's really right. This is isn't the first code attempt to detect the correct location of the crt, which actually won't be correct for things like Musl installs. The current code represents a best effort with the --linux-* being intended to solve the problem when the heuristics fail.

If you are interested in contributing some improvement to this code then you're very welcome to do so, but it takes some love from linux users to improve. The current solution has been programmed and tested using CI to debug / test. Extremely time consuming.

@lerno lerno added Enhancement Request New feature or request Help Wanted! Community help would be great! labels Dec 29, 2024
@matteac
Copy link
Author

matteac commented Dec 30, 2024

I hadn’t really considered how messy Linux can be in this regard. Honestly, I don’t know much about glibc/musl or crt, but given that the current approach assumes crtbegin is located in /usr/lib/gcc/*/*, we could lean into that assumption even more and do something like this:

static const char *get_linux_crt_begin_arch_glob(void) {
  switch (compiler.build.arch_os_target) {
  // It might be <arch>-linux-gnu or <arch>-pc-linux-gnu 
  case LINUX_X64:
    return "/usr/lib/gcc/x86_64*linux*/*/crtbegin.o";
  case LINUX_X86:
    return "/usr/lib/gcc/i686*linux*/*/crtbegin.o";
  case LINUX_AARCH64:
    return "/usr/lib/gcc/aarch64*linux*/*/crtbegin.o";
  case LINUX_RISCV32:
  case LINUX_RISCV64:
  default:
    return "/usr/lib/gcc/*/*/crtbegin.o";
  }
}

It’s not the cleanest solution and feels a bit hacky, but as I mentioned, I’m not super familiar with the topic or the codebase.

@lzace817
Copy link

I've found this for musl on debian:

/usr/lib/x86_64-linux-musl/Scrt1.o
/usr/lib/x86_64-linux-musl/crt1.o
/usr/lib/x86_64-linux-musl/crti.o
/usr/lib/x86_64-linux-musl/crtn.o
/usr/lib/x86_64-linux-musl/libc.a
/usr/lib/x86_64-linux-musl/libdl.a
/usr/lib/x86_64-linux-musl/libm.a
/usr/lib/x86_64-linux-musl/libpthread.a
/usr/lib/x86_64-linux-musl/libresolv.a
/usr/lib/x86_64-linux-musl/librt.a
/usr/lib/x86_64-linux-musl/libutil.a
/usr/lib/x86_64-linux-musl/libxnet.a
/usr/lib/x86_64-linux-musl/musl-gcc.specs
/usr/lib/x86_64-linux-musl/rcrt1.o

I guess the corresponding notion of crtstart.o & crtend.o on musl are crti.o and crtn.o.

source

https://packages.debian.org/bookworm/amd64/musl-dev/filelist

@matteac
Copy link
Author

matteac commented Dec 30, 2024

I've been playing with Alpine Linux. crtbegin.o and crtend.o are provided by GCC in /usr/lib/gcc/x86_64-alpine-linux-musl. I’m not sure about Debian with musl, but in Alpine, /usr/lib/gcc/x86_64*linux*/*/crtbegin.o should also match the correct directory

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Request New feature or request Help Wanted! Community help would be great!
Projects
None yet
Development

No branches or pull requests

3 participants