I need to programmatically inspect the library dependencies of a given executable. Is there a better way than running the ldd
(or objdump
) commands and parsing their output? Is there an API available which gives the same results as ldd
?

- 6,373
- 5
- 31
- 60
1 Answers
I need to programmatically inspect the library dependencies of a given executable.
I am going to assume that you are using an ELF system (probably Linux).
Dynamic library dependencies of an executable or a shared library are encoded as a table on Elf{32_,64}_Dyn
entries in the PT_DYNAMIC
segment of the library or executable. The ldd
(indirectly, but that's an implementation detail) interprets these entries and then uses various details of system configuration and/or LD_LIBRARY_PATH
environment variable to locate the needed libraries.
You can print the contents of PT_DYNAMIC
with readelf -d a.out
. For example:
$ readelf -d /bin/date
Dynamic section at offset 0x19df8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x3000
0x000000000000000d (FINI) 0x12780
0x0000000000000019 (INIT_ARRAY) 0x1a250
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1a258
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x308
0x0000000000000005 (STRTAB) 0xb38
0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 946 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1b000
0x0000000000000002 (PLTRELSZ) 1656 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x2118
0x0000000000000007 (RELA) 0x1008
0x0000000000000008 (RELASZ) 4368 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffb (FLAGS_1) Flags: PIE
0x000000006ffffffe (VERNEED) 0xf98
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0xeea
0x000000006ffffff9 (RELACOUNT) 170
0x0000000000000000 (NULL) 0x0
This tells you that the only library needed for this binary is libc.so.6
(the NEEDED
entry).
If your real question is "what other libraries does this ELF binary require", then that is pretty easy to obtain: just look for DT_NEEDED
entries in the dynamic symbol table. Doing this programmatically is rather easy:
- Locate the table of program headers (the ELF file header
.e_phoff
tells you where it starts). - Iterate over them to find the one with
PT_DYNAMIC
.p_type
. - That segment contains a set of fixed sized
Elf{32,64}_Dyn
records. - Iterate over them, looking for ones with
.d_tag == DT_NEEDED
.
Voila.
P.S. There is a bit of a complication: the strings, such as libc.so.6
are not part of the PT_DYNAMIC
. But there is a pointer to where they are in the .d_tag == DT_STRTAB
entry. See this answer for example code.

- 199,314
- 34
- 295
- 362
-
Hi, thanks for your answer. It has gotten me one step closer to me ideal solution, but I'm not there yet. I'm assuming that you're suggesting to parse the ELF binary and not literally use the `readelf` tool, right? I'm doing this in Haskell, and I found https://hackage.haskell.org/package/elf-0.30/docs/Data-Elf.html which does the job of parsing an ELF binary. – Saurabh Nanda Mar 29 '20 at 15:30
-
a parsed ELF binary is represented by this Haskell record - https://hackage.haskell.org/package/elf-0.30/docs/Data-Elf.html#t:Elf - and each section in the binary is represented by https://hackage.haskell.org/package/elf-0.30/docs/Data-Elf.html#t:ElfSegment . I can find the segment with `elfSegmentType==PT_DYNAMIC`, but what next? It seems like the data for all elf-segments is represented by an opaque `ByteString`. Am I right in concluding that the library doesn't parse the data of each segment (depending upon the segment-type)? – Saurabh Nanda Mar 29 '20 at 15:33
-
@SaurabhNanda: Correct: I am suggesting parsing the data directly. Also correct: it doesn't look like Data-Elf is looking into the contents of the segments. You'll have to write code to do so (but that is quite easy). – Employed Russian Mar 29 '20 at 15:42
-
Do you know of a simple document that explains the format of the `PT_DYNAMIC` section? Also, as you've mentioned in your answer, this section will not contain the literal strings, but references to strings. Does it look like https://hackage.haskell.org/package/elf-0.30/docs/Data-Elf.html#v:parseSymbolTables is already parsing all such strings? – Saurabh Nanda Mar 29 '20 at 15:46
-
@SaurabhNanda This answer *told* you the format of `PT_DYNAMIC`: it's a set of fixed-sized ElfXX_Dyn records. The strings are just literal ASCII strings packed one after the other in one of the `PT_LOAD` segments. You'll have to find that load segment by decoding `PT_DYNAMIC` first. – Employed Russian Mar 29 '20 at 15:54
-
Thanks. Let me try to work something out. Your answer address my original question. I'll need to figure out how to get this working in Haskell. Thank you for the detailed answer and being kind enough to address my follow-up questions. – Saurabh Nanda Mar 29 '20 at 16:00