haampie / libtree

ldd as a tree
MIT License
2.63k stars 60 forks source link

Support FreeBSD + avoid hard-coding excluded library versions #45

Open ararslan opened 2 years ago

ararslan commented 2 years ago

Summary/motivation of changes:

With these changes, libtree builds and passes all tests on FreeBSD 12.2 on x86_64.

haampie commented 2 years ago

Thanks Alex! This is great!

I noticed a few more things, but that shouldn't block this PR:

  1. There is a $PLATFORM variable that can be interpolated in rpaths, not sure where it is taken from if not from getauxval
  2. FreeBSD has $OSNAME, $OSREL variables but not $LIB in rpaths
  3. FreeBSD has multiple config files for search paths: /etc/ld.so.conf and /etc/ld-elf.so.conf, is the latter included by the former?
ararslan commented 2 years ago

Ah, good notes!

  1. I didn't realize FreeBSD had $PLATFORM, I wonder in what cases it's used. I looked at the RTLD source and this, as well as $OSNAME and $OSREL, come from uname. So e.g.

    #include <sys/utsname.h>
    // ...
    struct utsname* uts;
    uname(uts);
    printf("$PLATFORM: %s\n$OSNAME: %s\n$OSREL: %s\n",
          uts->machine, uts->sysname, uts->release);

    In case you're curious, the source I was looking at is here. I'll amend the platform substitution part of the PR and add the OS name and release to the regex substitutions.

  2. I guess I should move the $LIB substitution into a Linux-only conditional.

  3. I can't find any information or documentation about /etc/ld.so.conf, I can only find /etc/ld-elf.so.conf. So I guess the latter is the only one we'd need to care about, then?

ararslan commented 2 years ago

Okay I figured out the BSD-specific substitutions but I don't love how I did it (passing around a utsname object in addition to platform, which may come from the utsname). Do you know whether there are cases where getauxval(AT_PLATFORM) and .machine from utsname won't be the same? If they'll always be equal, we should be able to just use utsname everywhere and drop getauxval.

haampie commented 2 years ago

Hm, another option is to work with a list of regexes + replacements ~Vector{Pair{Regex,String}}~ std::vector<std::pair<std::regex,std::string>>> and populate them in main and pass them to tree, if that makes life easier.

For me AT_PLATFORM / .machine are equal strings but they're not the same pointer (I hoped the one would call the other :p)

ararslan commented 2 years ago

Oh true. I can implement that here if you think that'd be a better solution. I don't have much of an opinion.

haampie commented 2 years ago

FYI, Linus Torvalds wrote this 17 years ago:

/* This yields a string that ld.so will use to load implementation
   specific libraries for optimization.  This is more specific in
   intent than poking at uname or /proc/cpuinfo.  */

In Linux it goes roughly like this:

#define ELF_PLATFORM <something in some arch/.../include/.../elf.h>
const char *k_platform = ELF_PLATFORM;
copy_to_user(u_platform, k_platform, len)
NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform);
haampie commented 2 years ago

Meanwhile though ...

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/elf.h#n238

/* I'm not sure if we can use '-' here */
#define ELF_PLATFORM       ("x86_64")

:laughing: