Re: [PATCH v2] gdb: add support for handling core dumps on arm-none-eabi

Simon Marchi
2020-10-06T17:37:52Z

On 2020-10-06 12:59 p.m., Paul Mathieu via Gdb-patches wrote:
> There are also some notes in the linux binary that look nice:
>
> ➜ bin readelf --notes screen
>
> Displaying notes found in: .note.gnu.build-id
> Owner Data size Description
> GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
> Build ID: 76c649229b0402d6a0d1f65c3925e85fcb18e79d
>
> Displaying notes found in: .note.ABI-tag
> Owner Data size Description
> GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
> OS: Linux, ABI: 3.2.0
>
> My own bare-metal executable contains no notes at all.
> Again, here, I'm not sure how widespread these notes are, and if linux
> really requires them to run the binary or not.
> As the note name suggests, it looks like a GNU extension, which
> implies that it's not mandatory?

I thought that the ABI version tag was ubiquitous enough, because of:

https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html

But I just checked in an Alpine system (which uses musl as the libc,
busybox for the core utils, and pretty much no GNU stuff):

$ docker run -it alpine
/ # apk add binutils
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
(1/3) Installing libgcc (9.3.0-r2)
(2/3) Installing libstdc++ (9.3.0-r2)
(3/3) Installing binutils (2.34-r1)
Executing busybox-1.31.1-r16.trigger
OK: 17 MiB in 17 packages
/ # readelf -n /bin/busybox
/ #

So the question is not arm-specific. Here, how would we differentiate
this busybox executable from a bare-metal x86-64 executable, and know
that the busybox one is made to run on Linux and not the other one.

> I found one more thing, trying to find differences between the 2 files.
>
> ➜ bin readelf --arch-specific screen
> Attribute Section: aeabi
> File Attributes
> Tag_CPU_name: "7-A"
> Tag_CPU_arch: v7
> Tag_CPU_arch_profile: Application
> Tag_ARM_ISA_use: Yes
> Tag_THUMB_ISA_use: Thumb-2
> Tag_FP_arch: VFPv3-D16
> Tag_ABI_PCS_wchar_t: 4
> Tag_ABI_FP_rounding: Needed
> Tag_ABI_FP_denormal: Needed
> Tag_ABI_FP_exceptions: Needed
> Tag_ABI_FP_number_model: IEEE 754
> Tag_ABI_align_needed: 8-byte
> Tag_ABI_align_preserved: 8-byte, except leaf SP
> Tag_ABI_enum_size: int
> Tag_ABI_VFP_args: VFP registers
> Tag_CPU_unaligned_access: v6
>
> ➜ bin readelf --arch-specific my_bare_metal_stuff.elf
> Attribute Section: aeabi
> File Attributes
> Tag_CPU_name: "8-M.MAIN"
> Tag_CPU_arch: v8-M.mainline
> Tag_CPU_arch_profile: Microcontroller
> Tag_THUMB_ISA_use: Yes
> Tag_FP_arch: FPv5/FP-D16 for ARMv8
> Tag_ABI_PCS_wchar_t: 4
> Tag_ABI_FP_denormal: Needed
> Tag_ABI_FP_exceptions: Needed
> Tag_ABI_FP_number_model: IEEE 754
> Tag_ABI_align_needed: 8-byte
> Tag_ABI_enum_size: small
> Tag_ABI_VFP_args: VFP registers
> Tag_CPU_unaligned_access: v6
> Tag_DSP_extension: Allowed
>
> The Tag_CPU_arch_profile value is different, and looks like I could use that.
> Alan, would you say this tag is meaningful & reliable?

From what I read, this is just the "ARM profile", meaning the letter in
the ARM processor model number. Cortex M0 == M (Microcontroller).
Cortex A53 -> A (Application). So not very reliable, it doesn't
indicate whether or not you're running an OS.

>> Just so we are on the same page as to why this is happening, can you try
>> to step into function "gdbarch_info_fill" while you're executable is
>> loaded?
>>
>> What I think is happening is that gdbarch_lookup_osabi returns
>> GDB_OSABI_UNKNOWN, because no sniffer identified it.
>>
>> So the default osabi of your build gets used instead:
>>
>> /* From the configured default. */
>> #ifdef GDB_OSABI_DEFAULT
>> if (info->osabi == GDB_OSABI_UNKNOWN)
>> info->osabi = GDB_OSABI_DEFAULT;
>> #endif
>
> That looks right. `gdbarch_lookup_osabi` indeed returns GDB_OSABI_UNKNOWN.
> Here's what I get in gdb after loading the main file:
>
> (gdb) show osabi
> The current OS ABI is "auto" (currently "GNU/Linux").
> The default OS ABI is "GNU/Linux".

Thanks.

>> So indeed, if there was a sniffer identifying the binary as a "none"
>> osabi, it would probably work. The problem is, how do you write such a
>> sniffer? It's easy to check for a Linux binary, you check for the os
>> abi ELF note.
>
> As mentioned above, I looked into ELF file differences between
> arm-linux and arm-none and couldn't find anything of substance. Am I
> missing something?

I don't think so. Well, the closest thing is .note.ABI-tag, but since
that it's not _always_ there... note sure we can rely on it.

>> But how do you identify a "none" binary? You would have
>> to check that's it's not a Linux binary, not FreeBSD binary, not a
>> Windows binary, etc.
>
> Agreed. There seems to be a sniffer for PikeOS, which looks for a
> specific symbol in the symbol table. There is a comment in there
> saying that the BFD target is otherwise just standard ELF. I'm afraid
> that if I was to use a trick, such as the Tag_CPU_arch_profile
> mentioned above, I would prevent some other targets from working
> properly.

Indeed. I don't think sniffers have a concept of priority at the
moment, but we could think of adding that. Since the PikeOS sniffer is
more specific, it would have a higher priority than yours, so would run
first. So you would catch whatever was not identified as PikeOS.

>> I don't really like the idea of having a "default" osabi that we fall
>> back on, because it can just silently get it wrong, like in this case.
>> I think it would make more sense for the fall back to be "none".
>> Because it's hard to detect a "none" binary, as explained above.
>
> I looked into configure.tgt, and it looks like default osabi is only
> set for targets that have -linux in them. I'm building gdb with
> `./configure --enable-targets=arm-none-eabi`, should that help? In my
> case, the resulting gdb program still crashes with the same message.
> Interestingly, it also prints out a warning:
>
> warning: A handler for the OS ABI "GNU/Linux" is not built into this
> configuration
> of GDB. Attempting to continue with the default armv8-m.main settings.
>
> I think in this case, the fact that it uses linux as a default osabi
> could be a bug?

Not sure. When you use --enable-targets=arm-none-eabi, I think that it
implicitly still uses --target=x86_64-pc-linux-gnu or something
(assuming you work on x86-64 GNU/Linux). --enable-targets is used to
add more targets than the default one provided by --target.

You end up with this message because:

1. You built GDB with arm/none and x86-64/linux. You did not include
arm/linux.
2. The "default osabi", as set in configure.tgt, is Linux, because your
--target is something-something-linux.
3. The architecture of your executable is ARM, the osabi GDB tries to
use is "Linux" (because it's the fall back), and it proceeds to
complain that you don't have support for arm/linux.

So, not really a bug, it's kind of expected due to your configuration
and how the default fall back osabi is decided.

Simon