Closed oleid closed 8 months ago
You're welcome.
I'm familiar with Canape. I would assume that most people who are interested in a2ltool will be using Vector tools (Canape or Canoe.XCP) at some point.
Writing arrays as "VarName._0_" instead of "VarName[0]" is the old, backward compatible notation, because older file versions (<1.6) don't accept "[" and "]" as valid components of the variable name. Since then this has been added, so "VarName[0]" is allowed. Version 1.6 was standardized 13 years ago, so basically everyone should be using software that can handle both forms.
a2ltool also understands both notations, so I think your variable is not an array, or it was not recognized as an array when loading the debug data from the elf file. You can pass the "--debug-print" parameter to dump the dictionary of variables and types. You'll want to redirect the output to a text file if you do that, e.g. "a2ltool [...] --debug-print > output.txt" You can search for the name of the variable in the output, where you'll find something like this:
"MyGlobalVariable": VarInfo {
address: 123456789,
typeref: 11111111,
},
The typeref is a unique number identifying the type, which you can also search for, and then you might find something like this:
11111111: Array {
size: 212,
dim: [
53,
],
stride: 4,
arraytype: Float,
}
This way you can check if the data type of your variable is an array, rather than a struct or a plain data type.
Thanks for your answer!
Indeed I found the VarInfo:
"SomeVoltage": VarInfo {
address: 1073843978,
typeref: 300800,
},
But I cannot find 300800
anywhere else in the output.
Digging through the generated type information, I find various types: different POD, enums, structs and so on, but no array at all.
The arrays are defined as follows in the C code:
static unsigned short SomeVoltage[NUM_OF_VOLTAGES];
Using llvm-dwarfdump-15 -a
I can indeed see the type information:
0x000466d6: DW_TAG_variable
DW_AT_decl_file ("path/to/file.c")
DW_AT_decl_line (32)
DW_AT_decl_column (23)
DW_AT_name ("SomeVoltage")
DW_AT_type (0x0000000000049700 "unsigned short[80]")
DW_AT_location (DW_OP_addr 0x40018f0a)
[...]
0x00049700: DW_TAG_array_type
DW_AT_sibling (0x0004970c)
DW_AT_type (0x000000000004957c "unsigned short")
So I presume a2ltool or gimli for that matter should be able to identify the array correctly. I'll dig into the source code to check if I can find the issue.
The code in typereader.rs reads the types from the DWARF info, the relevant code for arrays is on line 68 and following. For this code to work correctly, every array needs an array type, which I see in your dumped info, and a size attribute (DW_AT_byte_size), which I do not see. The byte size is needed to calculate the array length (array size / element size = length).
If you enable verbose output (-v) do you get any messages like this: "Error loading type info for variable SomeVoltage: error decoding array info: missing size attribute"?
If you enable verbose output (-v) do you get any messages like this: "Error loading type info for variable SomeVoltage: error decoding array info: missing size attribute"?
Indeed, I see lots of those messages including the SomeVoltage
variable I mentioned before.
For this code to work correctly, every array needs an array type, which I see in your dumped info, and a size attribute (DW_AT_byte_size), which I do not see.
So the question boils down to why the llvm based tools ( I meanwhile checked llvm-symbolizer as well) manage to get a proper array length and gimli does not.
The problem is not with gimli, which just provides the mechanism to read the debug info entries.
Rather, it looks like your compiler is emitting a different combination of attributes than the ones I have seen so far. Therefore the code in typereader.rs, which was written by me, is not handling your compilers output correctly.
Clearly the info about the array length must be in there somehow, since llvm-dwarfdump was able to display "unsigned short[80]"
The problem is not with gimli, which just provides the mechanism to read the debug info entries.
You're right, I got confused with gimli's dwarfdump example not printing the type info. Readelf was able to give me an idea how the information is encoded:
<1><466d6>: Abbrev Number: 4 (DW_TAG_variable)
<466d7> DW_AT_decl_file : 0x1
<466db> DW_AT_decl_line : 32
<466dc> DW_AT_decl_column : 23
<466dd> DW_AT_name : SomeVoltage
<466ed> DW_AT_type : <0x49700>
<466f1> DW_AT_location : 5 byte block: 3 40 1 8f a (DW_OP_addr: 40018f0a)
[...]
<1><49700>: Abbrev Number: 26 (DW_TAG_array_type)
<49701> DW_AT_sibling : <0x4970c>
<49705> DW_AT_type : <0x4957c>
<2><49709>: Abbrev Number: 27 (DW_TAG_subrange_type)
<4970a> DW_AT_upper_bound : 79
<2><4970b>: Abbrev Number: 0
Apparently, the length is encoded as child of the array type entry. The array is 80 elements long. According to https://developer.ibm.com/articles/au-dwarf-debug-format/, one can extract the array size as follows:
Extract array size
The immediate child of DW_TAG_array_type is DW_TAG_subrange_type, which has the array size. Array size is calculated as (DW_AT_upper_bound- DW_AT_lower_bound) +1. If it is a two-dimensional array, there will be an immediate sibling of type DW_TAG_subrange_type again. In this case, the array size is 8 (7+1).
EDIT:
Apparrently, there is already code in place to read the subrange type. As-is the code just assumes size is additionally set as an attribute.
EDIT2:
Okay, I've a local change that appears to work. Will send a PR soon.
Thanks for writing this tool! Looks great, so far!
I was trying to update the addresses of an existing file, which somebody produced with a tool called CANape. Apparently, the person mapped the individual elements of an array to individual measurements:
and so on. The elf file lists
SomeVoltage
(dumped with the objdump example of theobject
crate):But apparently, the entries get removed when running
--update
.From the output of
--help
I figured the format of the entries is possibly wrong, thus, I tried adding an array value as follows:So I keep wondering what the correct way of arrays is. Any help would be appreciated.