rucc_debug/shape.rs
1//! What the program means: the types a unit describes and the functions it defines.
2//!
3//! Design: `spec/11-asm-objects-debug.md` section 11.4.
4//!
5//! The line table answers where an address came from. This answers what the thing at that address
6//! is: which function a program counter is inside, what that function takes and gives back, and
7//! what the types in its signature are made of. A backtrace needs the first, and printing anything
8//! at all needs the rest.
9//!
10//! # A table of shapes rather than the compiler's own types
11//!
12//! Nothing here is a C type. A [`Shape`] is a DWARF entry with its attributes already decided, so
13//! the questions C answers and DWARF does not, which is most of them, are settled before anything
14//! reaches this crate. Whoever builds the table decides what `long` is on this target, which of two
15//! spellings of one width to write, whether a record is complete and where a bit-field's bits sit.
16//! What is left here is writing entries down, which is the part that has to be right about DWARF
17//! and has no opinion about C.
18//!
19//! It costs one thing, which is that a table can say something C cannot mean, and the answer to
20//! that is the same as for the machine IR: the writer is not a checker and the thing that would
21//! catch it is a reader. `readelf --debug-dump=info` is that reader and is what the differential
22//! runs.
23//!
24//! Every reference between entries is an index into the unit's [`types`] table, because a table of
25//! indices can be built in one pass over a recursive type without the borrow checker having
26//! anything to say about it, and because a cycle is ordinary rather than special: `struct node {
27//! struct node *next; }` is a pointer whose target is the record that holds it, and an index says
28//! that with nothing added.
29//!
30//! # What is described and what is skipped
31//!
32//! An [`Option<usize>`] target is DWARF's own convention, where the absence of a `DW_AT_type` means
33//! `void`. A type this compiler cannot yet describe is not that: a function that mentions one gets
34//! no [`Sig`], and a function with no `Sig` gets no `DW_TAG_subprogram` at all, so a debugger falls
35//! back to the symbol table for it the way it does for every function today. The alternative is an
36//! entry that says `void` or `void *` where the program said something else, and a debugger showing
37//! a wrong type is worse than one showing none.
38//!
39//! [`types`]: crate::Unit::types
40
41/// How the bits of a base type are read, which is DWARF's `DW_AT_encoding`.
42///
43/// The set C needs and no more. An enumeration rather than the `DW_ATE_` constants themselves so
44/// that whoever builds a table does not have to depend on `gimli` to name one.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum Encoding {
47 /// `bool`, whose one byte holds zero or one.
48 Boolean,
49 /// A signed integer in two's complement.
50 Signed,
51 /// An unsigned integer.
52 Unsigned,
53 /// `char` where it is signed, which DWARF keeps apart from a signed integer because a debugger
54 /// prints one as a character and the other as a number.
55 SignedChar,
56 /// `char` where it is unsigned, and `unsigned char`.
57 UnsignedChar,
58 /// One of the real floating types.
59 Float,
60 /// `_Complex T`, whose bytes are the real half and then the imaginary one.
61 Complex,
62}
63
64/// A qualifier, which DWARF writes as an entry wrapping the type it qualifies.
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum Qualifier {
67 /// `const`.
68 Const,
69 /// `volatile`.
70 Volatile,
71 /// `restrict`.
72 Restrict,
73 /// `_Atomic`, which C calls a type rather than a qualifier and DWARF writes like one.
74 Atomic,
75}
76
77/// Which bits of a record a bit-field member is.
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79pub struct Bits {
80 /// How far into the record the first bit is, in bits from the start of it.
81 ///
82 /// Bits from the start of the whole record and not from the start of some storage unit, which
83 /// is what `DW_AT_data_bit_offset` means and is the one of DWARF's two spellings that does not
84 /// depend on the reader working out which unit was meant or which way round the target is.
85 pub at: u64,
86 /// How many bits it is, which is the width the program wrote.
87 pub width: u64,
88}
89
90/// One member of a record.
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct Member {
93 /// Its name, absent for an anonymous `struct` or `union` member and for an unnamed bit-field.
94 pub name: Option<String>,
95 /// Which of the unit's [`types`](crate::Unit::types) it is.
96 pub ty: usize,
97 /// How far into the record it starts, in bytes. Meaningless for a bit-field, which says where
98 /// it is in [`Member::bits`] instead.
99 pub at: u64,
100 /// Which bits it is, for a bit-field, and [`None`] for an ordinary member.
101 pub bits: Option<Bits>,
102}
103
104/// One type, in the terms DWARF describes one.
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub enum Shape {
107 /// A type whose bytes are read directly, which is every arithmetic type C has.
108 Base {
109 /// What it is called, which is the spelling the program would have written.
110 name: String,
111 /// How its bits are read.
112 encoding: Encoding,
113 /// How many bytes it is.
114 size: u64,
115 },
116 /// A pointer, whose target is [`None`] for `void *`.
117 Pointer {
118 /// Which of the unit's [`types`](crate::Unit::types) it points at.
119 to: Option<usize>,
120 /// How many bytes the pointer itself is.
121 size: u64,
122 },
123 /// An array, whose length is [`None`] when it has none a number can say.
124 ///
125 /// That covers three C spellings at once: the flexible array member, the array of unknown
126 /// length, and the array whose length is an expression. DWARF can describe the last of those
127 /// with an expression of its own, which is worth doing and is not done here, and leaving the
128 /// bound out is the answer a debugger already has to handle for the other two.
129 Array {
130 /// Which of the unit's [`types`](crate::Unit::types) the elements are.
131 of: usize,
132 /// How many of them there are.
133 count: Option<u64>,
134 },
135 /// A `struct` or a `union`, whose members are [`None`] when it is incomplete.
136 Record {
137 /// Whether it is a `union` rather than a `struct`.
138 union: bool,
139 /// Its tag, absent for one the program left anonymous.
140 name: Option<String>,
141 /// How many bytes it is, and nothing for an incomplete one.
142 size: Option<u64>,
143 /// The members in the order they were written, and [`None`] for an incomplete record,
144 /// which is a different thing from a complete record with no members.
145 members: Option<Vec<Member>>,
146 },
147 /// An `enum`.
148 Enumeration {
149 /// Its tag, absent for one the program left anonymous.
150 name: Option<String>,
151 /// Which of the unit's [`types`](crate::Unit::types) the enumerators are held in.
152 of: usize,
153 /// How many bytes it is.
154 size: u64,
155 /// The enumerators in the order the program wrote them.
156 ///
157 /// Empty for an enumeration that has not been completed, which is a thing a C program can
158 /// mention but cannot have an object of.
159 values: Vec<Constant>,
160 },
161 /// A `typedef` name for another type.
162 Alias {
163 /// The name.
164 name: String,
165 /// Which of the unit's [`types`](crate::Unit::types) it stands for, and [`None`] for a
166 /// name for `void`.
167 of: Option<usize>,
168 },
169 /// A qualified version of another type.
170 Qualified {
171 /// Which qualifier.
172 which: Qualifier,
173 /// Which of the unit's [`types`](crate::Unit::types) it qualifies, and [`None`] for
174 /// qualified `void`.
175 of: Option<usize>,
176 },
177 /// A function type, which is what a pointer to a function points at.
178 Subroutine(Sig),
179}
180
181/// One enumerator of an enumeration.
182#[derive(Debug, Clone, PartialEq, Eq)]
183pub struct Constant {
184 /// The name the program wrote, which is what a debugger prints in place of the number.
185 pub name: String,
186 /// Its value.
187 ///
188 /// Wider than any enumeration a target has, so that the writer decides which DWARF form the
189 /// number goes in rather than the caller having to know. A value wider than 64 bits has no
190 /// form that holds it and is left out, the same way a record drops a member it cannot
191 /// describe and keeps the rest.
192 pub value: i128,
193}
194
195/// What a function takes and gives back.
196#[derive(Debug, Clone, Default, PartialEq, Eq)]
197pub struct Sig {
198 /// Which of the unit's [`types`](crate::Unit::types) it returns, and [`None`] for `void`.
199 pub returns: Option<usize>,
200 /// The parameters in order.
201 pub params: Vec<Param>,
202 /// Whether it ends in `...`.
203 pub variadic: bool,
204 /// Whether the program wrote a parameter list rather than leaving it empty.
205 ///
206 /// `DW_AT_prototyped`, and it is not the same question as whether the list is empty: `int f()`
207 /// says nothing about what `f` takes and `int f(void)` says it takes nothing, and a debugger
208 /// that could not tell them apart would offer to call the first with no arguments.
209 pub prototyped: bool,
210}
211
212/// One parameter of a function.
213#[derive(Debug, Clone, PartialEq, Eq)]
214pub struct Param {
215 /// Its name, absent in a prototype that gave none and in a function type.
216 pub name: Option<String>,
217 /// Which of the unit's [`types`](crate::Unit::types) it is.
218 pub ty: usize,
219 /// Where the parameter is, and [`None`] where this compiler cannot yet say and for every
220 /// function type.
221 ///
222 /// A parameter is a local that happened to arrive in a register, so where it ends up is decided
223 /// the same way every other local's place is. See [`Local::spot`]. A function type never has
224 /// one, since a type is not a piece of code and has no frame or registers to be in.
225 pub spot: Option<Spot>,
226}
227
228/// One variable the unit defines at file scope.
229///
230/// Not the same problem as a local, and that is the whole reason this is here and a local is not.
231/// A file-scope variable is at one address for the whole of the program, so its location is the
232/// address of its own symbol and the linker fills it in, the same way it fills in a function's. A
233/// local's location is wherever the code happens to be keeping it at the program counter the
234/// debugger stopped at, which is a list rather than an expression, and that is the rest of
235/// tamnd/rucc#9.
236#[derive(Debug, Clone, Default, PartialEq, Eq)]
237pub struct Global {
238 /// Its name, as the C program spelled it, which is what the relocation asks the linker for.
239 pub name: String,
240 /// Which of the unit's [`types`](crate::Unit::types) it is, and [`None`] when this compiler
241 /// cannot yet say.
242 ///
243 /// A variable with nothing here still gets an entry, which is the one place the rule for a
244 /// function is turned around. A `DW_TAG_variable` with no `DW_AT_type` does not say `void`,
245 /// because nothing in C is a variable of type `void`, so a reader takes it as a variable whose
246 /// type was not recorded. The name and the address are worth having on their own: they are
247 /// what lets a debugger resolve the name at all, and a program that knows what it is looking
248 /// at can cast.
249 pub ty: Option<usize>,
250 /// Where it was declared, and nothing when that is not known.
251 pub decl: Option<Place>,
252 /// Whether anything outside this unit can see it, which is the opposite of `static`.
253 pub external: bool,
254}
255
256/// One local the program declared.
257///
258/// A parameter is not here even when it has a place. It is already a child of the subprogram, from
259/// the signature, and a second entry for it would be a second variable of the same name. What it
260/// gets instead is [`Param::spot`].
261#[derive(Debug, Clone, PartialEq, Eq)]
262pub struct Local {
263 /// Its name, as the C program spelled it.
264 pub name: String,
265 /// Which of the unit's [`types`](crate::Unit::types) it is, and [`None`] when this compiler
266 /// cannot yet say, which is the case [`Global::ty`] explains.
267 pub ty: Option<usize>,
268 /// Where it was declared, and nothing when that is not known.
269 pub decl: Option<Place>,
270 /// Where in the machine it is, over the addresses of the function it is in.
271 pub spot: Spot,
272}
273
274/// Where a local is over the addresses of the function it is in.
275///
276/// Which of the two a local gets is decided by what lowering did with it rather than by the
277/// optimization level. A local with a frame slot is in that slot from the first instruction of the
278/// function to the last, because the frame layout hands the slot out once and nothing moves it
279/// afterwards, and one expression says so. A scalar whose address is never taken is put in an SSA
280/// value instead, at every optimization level including `-O0`, and where the register allocator put
281/// that value changes from one program counter to the next.
282#[derive(Debug, Clone, PartialEq, Eq)]
283pub enum Spot {
284 /// In one place at every address in the function.
285 Always(Held),
286 /// In a place that depends on where the program counter is, said stretch by stretch.
287 ///
288 /// The stretches do not have to cover the function, and an address none of them covers is an
289 /// address the local is nowhere. That is the honest answer rather than a gap: a value that has
290 /// not been computed yet, or whose last reader is already behind, is somewhere for part of a
291 /// function and nowhere for the rest, and a debugger stopped in the rest should say the
292 /// variable is not available rather than print whatever is in the register now.
293 Over(Vec<Span>),
294}
295
296/// One stretch of a function's addresses and where a local is over it.
297#[derive(Debug, Clone, Copy, PartialEq, Eq)]
298pub struct Span {
299 /// How far into the function the stretch starts, in bytes.
300 pub from: u64,
301 /// How long it is, in bytes. A stretch of no length covers nothing and is refused.
302 pub len: u64,
303 /// Where the local is over it.
304 pub held: Held,
305}
306
307/// A place in the machine something can be.
308#[derive(Debug, Clone, Copy, PartialEq, Eq)]
309pub enum Held {
310 /// This far from the function's frame base, which is a negative number for anything in the
311 /// frame, since the frame base is the stack pointer the caller had and a frame is below that.
312 Frame(i64),
313 /// In this register, by the number this target's DWARF register numbering gives it.
314 ///
315 /// Not the register number the back end uses. The two agree on some targets and not on others,
316 /// and the translation is the caller's, because the caller is what knows which target this is.
317 Reg(u16),
318}
319
320/// Where in the source something was declared.
321#[derive(Debug, Clone, Copy, PartialEq, Eq)]
322pub struct Place {
323 /// Which of the unit's [`files`](crate::Unit::files) it is in.
324 pub file: usize,
325 /// Which line of that file, counting from one.
326 pub line: u32,
327}