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