avr-objdump and avrtiny

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm sure I've just overlooked a simple solution.

 

Consider:

$ cat foo.S

	lds	r24, 0x4c
	lds	r25, 0x41
	lds	r26, 0x50

$ avr-gcc -mmcu=attiny4 -mmcu=attiny4 -g -Wall -nostartfiles -save-temps foo.S -o foo.elf
$ avr-objdump -S foo.elf

foo.elf:     file format elf32-avr

Disassembly of section .text:

00000000 <__ctors_end>:
#include <avr/io.h>

        lds     r24, 0x4c
   0:   8c a1           lds     r24, 0x4c       ; 0x80004c <_edata+0xc>
        lds     r25, 0x41
   2:   91 a1           lds     r25, 0x41       ; 0x800041 <_edata+0x1>
        lds     r26, 0x50
   4:   a0 a3           lds     r26, 0x50       ; 0x800050 <_edata+0x10>

 

An Intel hex file can be passed to avr-objdump for disassembly:

$ avr-objcopy -O ihex -j .text foo.elf foo.hex
$ avr-objdump -Dzmavr foo.hex

foo.hex:     file format ihex

Disassembly of section .sec1:

00000000 <.sec1>:
   0:   8c a1           ldd     r24, Y+36       ; 0x24
   2:   91 a1           ldd     r25, Z+33       ; 0x21
   4:   a0 a3           std     Z+32, r26       ; 0x20

The difference is down to the fact that the 'brain-dead' tiny core supports only 16-bit instructions, and has a 16-bit version of the lds/sts instructions (rather than the 32-bit versions supported by the mega core), and the opcode encoding for lds/sts on avrtiny intersects the opcode encodings for ldd/std on the mega (and other) cores.

 

Now when I try to specify the correct core:

$ avr-objdump -Dzmavrtiny foo.hex

foo.hex:     file format ihex

avr-objdump: can't use supplied machine avrtiny

So it seems that avr-objdump is able to correctly identify the ISA to use when using the .elf as input, but it doesn't recognise the named ISA when passed on the command line.

 

Do I have the wrong machine type?

 

EDIT:  copy/paste errors

This topic has a solution.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sat. Feb 17, 2018 - 03:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use Readelf to look at the ELF that the first objdump is reading. Clearly something in the header conveys the correct architecture type.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The -A option reveals nothing.  Passing all possibly relevant options:

$ readelf -ahlSgtesnrudVADI foo.elf

... reveals nothing especially pertinent.  Here is an excerpt:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Atmel AVR 8-bit microcontroller
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          1012 (bytes into file)
  Flags:                             0x64
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         2
  Size of section headers:           40 (bytes)
  Number of section headers:         10
  Section header string table index: 7

 

Now compare that to the same source (from the OP) built for an m328p:

 

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Atmel AVR 8-bit microcontroller
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          1132 (bytes into file)
  Flags:                             0x5
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         2
  Size of section headers:           40 (bytes)
  Number of section headers:         10
  Section header string table index: 7

 

A diff of the two full outputs:

$ avr-gcc -mmcu=attiny4 -g -Wall -nostartfiles -save-temps foo.S -o foo.elf
$ avr-gcc -mmcu=atmega328p -g -Wall -nostartfiles -save-temps foo.S -o bar.elf
$ readelf -ahlSgtesnrudVADI foo.elf > foo.readelf
$ readelf -ahlSgtesnrudVADI bar.elf > bar.readelf
$ diff -rupN foo.readelf bar.readelf 
--- foo.readelf 2018-02-16 06:10:37.839813064 -0500
+++ bar.readelf 2018-02-16 06:10:44.280246142 -0500
@@ -10,8 +10,8 @@ ELF Header:
   Version:                           0x1
   Entry point address:               0x0
   Start of program headers:          52 (bytes into file)
-  Start of section headers:          1012 (bytes into file)
-  Flags:                             0x64
+  Start of section headers:          1132 (bytes into file)
+  Flags:                             0x5
   Size of this header:               52 (bytes)
   Size of program headers:           32 (bytes)
   Number of program headers:         2
@@ -26,12 +26,12 @@ Section Headers:
   [ 0]
        NULL            00000000 000000 000000 00   0   0  0
        [00000000]:
-  [ 1] .text
-       PROGBITS        00000000 000074 000006 00   0   0  2
-       [00000006]: ALLOC, EXEC
-  [ 2] .data
-       PROGBITS        00800040 00007a 000000 00   0   0  1
+  [ 1] .data
+       PROGBITS        00800100 000080 000000 00   0   0  1
        [00000003]: WRITE, ALLOC
+  [ 2] .text
+       PROGBITS        00000000 000074 00000c 00   0   0  2
+       [00000006]: ALLOC, EXEC
   [ 3] .debug_aranges
        PROGBITS        00000000 000080 000020 00   0   0  8
        [00000000]:
@@ -45,21 +45,21 @@ Section Headers:
        PROGBITS        00000000 0000e5 00003d 00   0   0  1
        [00000000]:
   [ 7] .shstrtab
-       STRTAB          00000000 000397 00005c 00   0   0  1
+       STRTAB          00000000 00040e 00005c 00   0   0  1
        [00000000]:
   [ 8] .symtab
-       SYMTAB          00000000 000124 000170 10   9   7  4
+       SYMTAB          00000000 000124 0001a0 10   9   7  4
        [00000000]:
   [ 9] .strtab
-       STRTAB          00000000 000294 000103 00   0   0  1
+       STRTAB          00000000 0002c4 00014a 00   0   0  1
        [00000000]: 

 There are no section groups in this file.

 Program Headers:
   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
-  LOAD           0x000074 0x00000000 0x00000000 0x00006 0x00006 R E 0x2
-  LOAD           0x00007a 0x00800040 0x00000006 0x00000 0x00000 RW  0x1
+  LOAD           0x000074 0x00000000 0x00000000 0x0000c 0x0000c R E 0x2
+  LOAD           0x000080 0x00800100 0x0000000c 0x00000 0x00000 RW  0x1

  Section to Segment mapping:
   Segment Sections...

 

So while there are some differences, nothing jumps out as a machine type which I can then pass to avr-objdump as an override.  Perhaps the most promising is the 'Flags:' field, but damned if I know what to make of it, or what to do with it.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Feb 16, 2018 - 11:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A list of supported architectures:

$ avr-objdump -i
BFD header file version (AVR_8_bit_GNU_Toolchain_3.5.4_1709) 2.26.20160125
elf32-avr
 (header little endian, data little endian)
  avr
elf32-little
 (header little endian, data little endian)
  plugin
  avr
elf32-big
 (header big endian, data big endian)
  plugin
  avr
plugin
 (header little endian, data little endian)
srec
 (header endianness unknown, data endianness unknown)
  plugin
  avr
symbolsrec
 (header endianness unknown, data endianness unknown)
  plugin
  avr
verilog
 (header endianness unknown, data endianness unknown)
  plugin
  avr
tekhex
 (header endianness unknown, data endianness unknown)
  plugin
  avr
binary
 (header endianness unknown, data endianness unknown)
  plugin
  avr
ihex
 (header endianness unknown, data endianness unknown)
  plugin
  avr

               elf32-avr elf32-little elf32-big plugin srec symbolsrec verilog 
        plugin --------- elf32-little elf32-big ------ srec symbolsrec verilog 
           avr elf32-avr elf32-little elf32-big ------ srec symbolsrec verilog 

               tekhex binary ihex 
        plugin tekhex binary ihex 
           avr tekhex binary ihex 

Note that 'avrtiny' is not among them, yet it is able to correction disassemble an .elf built for avrtiny (e.g. w.r.t. 16-it lds/sts).

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But that list looks like binary file types supported not "architectures" ?

 

Anyway I guess there's only one way to get to the bottom of this and that is to either "dry read" the source of objdump or perhaps even run it in an debugger and step its operation to see what "decisions" it is making and why.

Last Edited: Fri. Feb 16, 2018 - 11:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agreed, however:

$ man avr-objdump
.
.
.
       -i
       --info
           Display a list showing all architectures and object formats available for specification with -b or -m.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting comment here:

 

https://sourceware.org/git/gitwe...

 

So sounds like bfd_check_format() is of some interest in this. It lives here:

 

https://sourceware.org/git/gitwe...

 

The "meat" seems to start around line 274

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The original reduced tiny support didn't properly implement LDS /STS (which is 2-byte instead of 4-byte for non-rtiny). Hence some 16-bit LDS / STS encoding might appear like some other instruction, maybe also LDD etc. This is reasonable because LDD and STD addressing has even more restrictions than on non-rtiny, in particular reg+offset addressing is not available.

Therefore you may want to check whether the STS encoding is correct and it's just an objdump hiccup, or the encoding is plain garbage. Whatever the answer will be, you'll definitely want a newer toolchain and Binutils release (Binutils 2.29.1 at least).

avrfreaks does not support Opera. Profile inactive.

Last Edited: Fri. Feb 16, 2018 - 03:18 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Georg-Johan,

 

But he's starting with hand coded Asm opcodes - not C code generation?

 

The point seems to be that for the same source that produces an ELF and a HEX that if the ELF if fed to objdump it correctly recognises the architecture somehow and know how to disassemble things like "8c a1" but if you take the HEX that presumably contains the same 8C A1 and try to use -m on the objdump it disassembles it differently.

 

I think he's really asking what is the magic -m "word" (when using HEX)  that says the same thing as the identity in the ELF did ?

 

Like Joey I would have expected "-m avrtiny" to do it. I suppose another way to look at this is that as Asm knowledge is added to binutils (is that in bfd or elsewhere?) how are new architectures added to the -m command?

 

EDIT: actually that prompted me to look for the list. So:

 

https://sourceware.org/git/gitwe...

 

appears to be the place and hence:

 

 102   /* Assembler only.  */
 103   N (16, bfd_mach_avr1, "avr:1", FALSE, & arch_info_struct[1]),
 104 
 105   /* Classic, <= 8K.  */
 106   N (16, bfd_mach_avr2, "avr:2", FALSE, & arch_info_struct[2]),
 107 
 108   /* Classic + MOVW, <= 8K.  */
 109   N (16, bfd_mach_avr25, "avr:25", FALSE, & arch_info_struct[3]),
 110 
 111   /* Classic, > 8K, <= 64K.  */
 112   /* TODO:  addr_bits should be 16, but set to 22 for some following
 113      version of GCC (from 4.3) for backward compatibility.  */
 114   N (22, bfd_mach_avr3, "avr:3", FALSE, & arch_info_struct[4]),
 115 
 116   /* Classic, == 128K.  */
 117   N (22, bfd_mach_avr31, "avr:31", FALSE, & arch_info_struct[5]),
 118 
 119   /* Classic + MOVW + JMP/CALL, > 8K, <= 64K. */
 120   N (16, bfd_mach_avr35, "avr:35", FALSE, & arch_info_struct[6]),
 121 
 122   /* Enhanced, <= 8K.  */
 123   N (16, bfd_mach_avr4, "avr:4", FALSE, & arch_info_struct[7]),
 124 
 125   /* Enhanced, > 8K, <= 64K.  */
 126   /* TODO:  addr_bits should be 16, but set to 22 for some following
 127      version of GCC (from 4.3) for backward compatibility.  */
 128   N (22, bfd_mach_avr5, "avr:5", FALSE, & arch_info_struct[8]),
 129 
 130   /* Enhanced, == 128K.  */
 131   N (22, bfd_mach_avr51, "avr:51", FALSE, & arch_info_struct[9]),
 132 
 133   /* 3-Byte PC.  */
 134   N (22, bfd_mach_avr6, "avr:6", FALSE, & arch_info_struct[10]),
 135 
 136   /* Tiny core (AVR Tiny).  */
 137   N (16, bfd_mach_avrtiny, "avr:100", FALSE, & arch_info_struct[11]),
 138 
 139   /* Xmega 1.  */
 140   N (24, bfd_mach_avrxmega1, "avr:101", FALSE, & arch_info_struct[12]),
 141 
 142   /* Xmega 2.  */
 143   N (24, bfd_mach_avrxmega2, "avr:102", FALSE, & arch_info_struct[13]),
 144 
 145   /* Xmega 3.  */
 146   N (24, bfd_mach_avrxmega3, "avr:103", FALSE, & arch_info_struct[14]),
 147 
 148   /* Xmega 4.  */
 149   N (24, bfd_mach_avrxmega4, "avr:104", FALSE, & arch_info_struct[15]),
 150 
 151   /* Xmega 5.  */
 152   N (24, bfd_mach_avrxmega5, "avr:105", FALSE, & arch_info_struct[16]),
 153 
 154   /* Xmega 6.  */
 155   N (24, bfd_mach_avrxmega6, "avr:106", FALSE, & arch_info_struct[17]),
 156 
 157   /* Xmega 7.  */
 158   N (24, bfd_mach_avrxmega7, "avr:107", FALSE, NULL)

So I guess the answer here is "-m avr:100" ??

 

(now I'm gonna have to go and test that!...)

Last Edited: Fri. Feb 16, 2018 - 03:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Result....

C:\SysGCC\avr\bin>avr-objdump -Dzmavr foo.hex

foo.hex:     file format ihex


Disassembly of section .sec1:

00000000 <.sec1>:
   0:   8c a1           ldd     r24, Y+36       ; 0x24
   2:   91 a1           ldd     r25, Z+33       ; 0x21
   4:   a0 a3           std     Z+32, r26       ; 0x20

C:\SysGCC\avr\bin>avr-objdump -Dzmavr:100 foo.hex

foo.hex:     file format ihex


Disassembly of section .sec1:

00000000 <.sec1>:
   0:   8c a1           lds     r24, 76
   2:   91 a1           lds     r25, 65
   4:   a0 a3           lds     r26, 80

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW just an observation (and the likely reason for the confusion here):

Known MCU names:
  avr1 avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1
  avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
  at90s1200 attiny11 attiny12 attiny15 attiny28 at90s2313 at90s2323
  at90s2333 at90s2343 attiny22 attiny26 at90s4414 at90s4433 at90s4434
  etc.

That is --target-help from avr-gcc. Those generic "family names" at the start of the list differ between the compiler and the binutils.

 

As we've just seen one uses avrtiny and the other avr:100 and that's also true for all the xmega ones too. I suppose even things like avr4 versus avr:4 are different but one can be derived from the other.

 

Presumably the naming rules for binutils are "chip_family:issue_number" or something?

 

Oh and if -i on objdump won't show "avr:4 .. avr:100, etc" then is there anyway to get it to dump it's "known names"?

 

(having said that, knowing that :100 meant "avrtiny" would be a bit of a leap of faith)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fantastisch!  That works with the binutils 2.26.20160125 which ships with the Atmel AVR8 toolchain 3.5.4 (the latest Linux binaries available, IINM).  Many thanks.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> -m avr:100
 
Great! I wasn't aware of that, and the docs are not very helpful, calling it the "bfdname", and I assumed that is the "target" or "architecture".
 
The tools have several means to categorize devices into "families" or "subsets":
 
-mmcu=avr* of avr-gcc / cc1[plus]: In the old days, -mmcu= served for multilib selection, i.e. to classify the devices according to their instruction set (usually after mapping devices to their respective avr* set). This is different today: First, there are more options for multilib selection like -msp8 and -mshort-calls. Second, options that determine ISA properties like -mrmw are /not/ used for multilib selection, or such options don't even exist (e.g. for DES).
 
__AVR_ARCH__: A built-in define (kind of) provided by the compiler proper or via specs-file so that user-code can use it in preprocessing directives. The number is the same like in the OUTPUT_ARCH of ld script.
 
-mavr* of the linker: Select the "emulation". Each emulation has it's own set of default linker scripts; this is basically the device-"granularity" of binutils, and less fine-grained than gcc's multilibs.
 
avr:100: The "OUTPUT_ARCH" property as specified in the default linker scripts. IIUC binutils could, in principle, check that all modules that are linked together are of the same arch so it could throw an error if one tries to link together incompatible objects. Here are different means that could be used for such sanity checks more fine grained than arch (e.g. not to link different ABI like -f[no]-short-enums together).
 
It would be highly desirable to get some documentation about what exactly are, and what are the differences between: "ARCH", "bfdname", "emulation" and "option". Clearly the -m option is just the name for some arch which is internally represented like a "100" or some enum. And it's also strange that objdump just dumps the "tiny" in -mavrtiny" instead of complaining about unknown arch.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very interesting info.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the detailed explanation.

 

And it's also strange that objdump just dumps the "tiny" in -mavrtiny" instead of complaining about unknown arch.

Well, it does complain:

$ avr-objdump -Dzmavrtiny foo.hex

foo.hex:     file format ihex

avr-objdump: can't use supplied machine avrtiny

 

Although "can't use supplied machine" isn't exactly the same as "unknown architecture".

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now that I know what I'm looking for:

https://www.google.ca/search?q="avr%3A100"+site%3Aavrfreaks.net

https://www.avrfreaks.net/comment/1992441#comment-1992441

avr-objdump: supported architectures: avr avr:1 avr:2 avr:25 avr:3 avr:31 avr:35 avr:4 avr:5 avr:51 avr:6 avr:100 avr:101 avr:102 avr:103 avr:104 avr:105 avr:106 avr:107

 

... which led to:

https://www.google.ca/search?q="avr-objdump%3A+supported+architectures%3A+avr+avr%3A1+avr%3A2+avr%3A25+avr%3A3+avr%3A31+avr%3A35+avr%3A4+avr%3A5+avr%3A51+avr%3A6+avr%3A100+avr%3A101+avr%3A102+avr%3A103+avr%3A104+avr%3A105+avr%3A106+avr%3A107"

https://helpmanual.io/help/avr-objdump/

 

So had I only:

$ avr-objdump --help
.
.
.
avr-objdump: supported targets: elf32-avr elf32-little elf32-big plugin srec symbolsrec verilog tekhex binary ihex
avr-objdump: supported architectures: avr avr:1 avr:2 avr:25 avr:3 avr:31 avr:35 avr:4 avr:5 avr:51 avr:6 avr:100 avr:101 avr:102 avr:103 avr:104 avr:105 avr:106 avr:107 plugin

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh dear God, I never thought of "help" blush

 

(Though connecting :100 to "avrtiny" is still a bit of a leap)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Though connecting :100 to "avrtiny" is still a bit of a leap

Yup, but Googling for:

"avr" "avr:1" "avr:2" "avr:25" "avr:3" "avr:31" "avr:35" "avr:4" "avr:5" "avr:51" "avr:6" "avr:100" "avr:101" "avr:102" "avr:103" "avr:104" "avr:105" "avr:106" "avr:107"

Leads me to source code such as that to which you linked in #9.  Which, how did you find that by the way?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just googled "binutils source" but it helps to know (from looking before) that the majority of tools (except readelf) are simply a "front" for libbfd so that's the "meat in the sandwich".