1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>
use debug::image;
use errors;
use format::elf;
use io;
export type abbrev_table = struct {
items: []abbrev,
};
// A single abbreviated tag from a .debug_abbrev section.
export type abbrev = struct {
code: u64,
tag: u32,
has_children: bool,
fields: []afield,
};
// A field in a .debug_abbrev section
export type afield = struct {
attr: u32,
form: u32,
};
// Loads an abbreviation table from the .debug_abbrev section, loading the table
// at the provided offset from the start of the ELF section.
//
// Pass the result to [[abbrev_table_finish]] to free resources associated with
// the table when you're done with it.
export fn load_abbrevs(
image: *image::image,
offs: u64,
) (abbrev_table | void | errors::invalid | nomem) = {
const sec = match (image::section_byname(image, ".debug_abbrev")) {
case let sec: *elf::section64 =>
yield sec;
case null =>
return;
};
const rd = image::section_reader(image, sec);
io::seek(&rd, offs: io::off, io::whence::SET)!;
const rd = new_table_reader(&rd, false)! as table_reader;
let abbrevs: []abbrev = [];
let ok = false;
defer if (!ok) {
free(abbrevs);
};
for (true) {
match (read_abbrev(&rd)) {
case io::EOF => break;
case io::error => return errors::invalid;
case nomem => return nomem;
case let ab: abbrev =>
append(abbrevs, ab)?;
};
};
ok = true;
return abbrev_table {
items = abbrevs,
};
};
// Reads an entry from an abbreviation table.
fn read_abbrev(
rd: *table_reader,
) (abbrev | io::EOF | io::error | nomem) = {
const code = read_uleb128(rd)?;
if (code == 0) {
return io::EOF;
};
const tag = read_uleb128(rd)?;
const children = read_ubyte(rd)? != 0;
let fields: []afield = [];
let ok = false;
defer if (!ok) {
free(fields);
};
for (true) {
const name = read_uleb128(rd)?;
const form = read_uleb128(rd)?;
if (name == 0 && form == 0) {
break;
};
append(fields, afield {
attr = name: u32,
form = form: u32,
})?;
};
ok = true;
return abbrev {
code = code,
tag = tag: u32,
has_children = children,
fields = fields,
};
};
// Frees resources associated with an [[abbrev_table]].
export fn abbrev_table_finish(table: *abbrev_table) void = {
for (let i = 0z; i < len(table.items); i += 1) {
free(table.items[i].fields);
};
free(table.items);
};
// Retrieves an abbreviation from an [[abbrev_table]] by its abbreviation code.
export fn get_abbrev(table: *abbrev_table, code: u64) const nullable *abbrev = {
// TODO: Sort the list and do this faster
for (let item &.. table.items) {
if (item.code == code) {
return item;
};
};
return null;
};
|