hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

abbrev.ha (2524B)


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