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

dwarf v4 debug types support #530

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

driftregion
Copy link

This builds on #520.

I've added a couple of .elf files produced by TI Code Composer studio C2000 compiler to the corpus.

My use-case is currently unblocked by these changes. pyelftools can parse the TI CCS files without crashing. However I haven't yet achieved llvm-dwarfdump consistency. Two issues have been solved but I'm at a loss on the third:

The relevant function is _desc_expression(expr, die): in dwarfdump.py

https://github.com/eliben/pyelftools/blob/master/scripts/dwarfdump.py#L277

And the mismatch is shown below:

....for file test/testfiles_for_dwarfdump/dwarf_v3_ticcs.elf
....for option "--debug-info"
....Output #1 is llvm-dwarfdump, Output #2 is pyelftools
@@ Mismatch on line #53:
>>                dw_at_location [dw_form_block1]       (dw_op_reg0)<<
>>              dw_at_location [dw_form_block1] (dw_op_reg0 r0)<<

Unlike the previous inconsistencies, when I attempt to modify this code I quickly break the other dwarfdump tests. I'm not yet sure if or how this should be special-cased.

Dinkar Khandalekar and others added 3 commits November 14, 2023 15:59
Changes
  * Support for parsing type units from the .debug_types section
  * Added logic to generate debug_types with readelf tool
  * Added test binaries generated using IAR Embedded Workbench for ARM toolchain (dwarf_debug_types.elf)

Known issues
  * When running unittests with new ELF binaries,
    * parsing of the .debug_frames section results in an infinite loop
    * parsing of the .debug_aranges section causes stream parsing errors
@eliben
Copy link
Owner

eliben commented Jan 1, 2024

@sevaa

@sevaa
Copy link
Contributor

sevaa commented Jan 19, 2024

@driftregion

First off, check the version of llvm-dwarfdump that you are testing against. Output format is not a contract, tool vendors change it all the time. We don't update llvm-dwarfdump in the test scripts folder every time they drop. This particular change looks like a bug fix on the LLVM side; DW_OP_regX doesn't take any arguments.

@driftregion
Copy link
Author

Hi seva, thanks for your response.

check the version of llvm-dwarfdump that you are testing against.

I'm running the tests on linux with the command

python test/run_dwarfdump_tests.py

I've confirmed that running this command uses test/external_tools/llvm-dwarfdump.

furthermore, I've tried using the dwarfdump installed on my machine by modifying test/run_dwarfdump_tests.py:38 to point to llvm-dwarfdump-15. it produces the same output as above #530 (comment)

llvm-dwarfdump-15  --version
Ubuntu LLVM version 15.0.7
  Optimized build.
  Default target: x86_64-pc-linux-gnu
  Host CPU: goldmont

test/external_tools/llvm-dwarfdump --version
LLVM (http://llvm.org/):
  LLVM version 15.0.0git
  Optimized build.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: goldmont

This particular change looks like a bug fix on the LLVM side; DW_OP_regX doesn't take any arguments.

Got it. Is there something other than the DWARF spec that specifies this? I'm reading DWARF Debugging Information Format, Version 4 and from this alone it is ambiguous to me whether DW_OP_reg0 takes arguments or not. Is there a more authoritative resource?

Screenshot from 2024-01-20 17-28-28

Screenshot from 2024-01-20 17-29-46

I had a quick look at the llvm bugtracker and found only this https://bugs.llvm.org/show_bug.cgi?id=38714 which seems to indicate that the arguments to DW_OP_reg are used.

@sevaa
Copy link
Contributor

sevaa commented Jan 21, 2024

DWARFv5 has been out for several years now. However, the DW_OP_regX operations have been stable since DWARFv2. The register number is a part of the opcode; one may interpret it as an implicit argument, but a low level parser, such as pyelftools, would be advised not to.

This is not about the spec, this is about matching the output of llvm-dwarfdump which is not governed by any spec. Have you tried looking at the sources of llvm-dwarfdump, see if there are any conditionals around that spot? You can build it for debudding and debug it, too.

@driftregion
Copy link
Author

Hey Seva, thanks for taking me on this adventure. This is wild. I learned a bunch of new gdb tricks and found that building llvm takes 114G of disk.

I found the conditional:

llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp:275

  auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH);
  if (!RegName.empty()) {

GetNameForDWARFReg points to a lambda which returns a StringRef which is empty in the case of the TI binary test/testfiles_for_dwarfdump/dwarf_v3_ticcs.elf. This is because createRegInfo returns NULL MCRegInfo for the TI binary due to target lookup failure.

test/testfiles_for_dwarfdump/dwarf_gnuops4.so.elf has non-NULL MCRegInfo and therefore prints the register names.

@sevaa
Copy link
Contributor

sevaa commented Jan 22, 2024

So looks like the logic is, for the handful of CPUs that llvm-dwarfdump is aware of, there is the logic of translating the register number to a friendly register name. Your TI binaries target a rather exotic (in the grand scheme of things, not in your own life) CPU. We have a similar logic in describe_reg_name() under elftools/dwarf/descriptions.py. It would return None for your TI binaries. The invokation of that function is in _desc_operation() in dwarfdump.py. If describe_reg_name() returns None, it should not print the friendly register name, but it does (?). Try debugging that piece on the Python side of things.

@driftregion
Copy link
Author

Great. python test/run_dwarfdump_tests.py passes now.

Note: TI's DWARF extensions (https://www.ti.com/lit/an/spraab5/spraab5.pdf?ts=1705994928599) are in conflict with and are incorrectly reported as HP dwarf attributes by llvm-dwarfdump (llvm/include/llvm/BinaryFormat/Dwarf.def:446)

@sevaa
Copy link
Contributor

sevaa commented Jan 23, 2024

Get rid of the custom dwarfdump please, or it will get in the way of the CI autotest. If you'd like an option to point at a dwarfdump of your choice, use an environment variable.

@driftregion
Copy link
Author

done in a612ffe

@nickvazz
Copy link

@eliben Wondering if this will get pulled in / released anytime soon. Thank you!

@eliben
Copy link
Owner

eliben commented Jun 23, 2024

@sevaa has been reviewing this, so I'll let him finish the review. @driftregion have all of @sevaa 's comments been addressed at this point?

@driftregion
Copy link
Author

@eliben , yes afaik

@sevaa
Copy link
Contributor

sevaa commented Jun 24, 2024

Yes.

elif attr.form in ('DW_FORM_ref_addr'):
return self.cu.dwarfinfo.get_DIE_from_refaddr(attr.raw_value)
elif attr.form in ('DW_FORM_ref_sig8'):
# Implement search type units for matching signature
raise NotImplementedError('%s (type unit by signature)' % attr.form)
die = self.cu.dwarfinfo.get_DIE_by_sig8(attr.raw_value)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: just return this directly, no need for a local die

@@ -134,6 +137,9 @@ def __init__(self,
self._cu_cache = []
self._cu_offsets_map = []

# DWARF v4 type units by sig8 - OrderedDict created on Reference
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what on Reference refers to here.

Do you mean to say it's lazily initialized the first time it's referenced?

"""
# All DIEs are after the cu header and within the unit

if refaddr == 10199037921532328682:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a debugging leftover?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants