hare

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

aranges.ha (1730B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use bufio;
      5 use debug::image;
      6 use errors;
      7 use encoding::hex;
      8 use format::elf;
      9 use io;
     10 use memio;
     11 
     12 // Supported version of .debug_aranges decoder
     13 def ARANGES_VERSION: u16 = 2;
     14 
     15 // Returns the debug_info offset for the DIE that corresponds to this address,
     16 // if known, or void if unknown.
     17 export fn arange_lookup(
     18 	image: *image::image,
     19 	addr: uintptr,
     20 ) (u64 | void | errors::invalid) = {
     21 	const aranges = match (image::section_byname(image, ".debug_aranges")) {
     22 	case let sec: *elf::section64 =>
     23 		yield sec;
     24 	case null =>
     25 		return;
     26 	};
     27 
     28 	// Read all arange tables in this section
     29 	const rd = image::section_reader(image, aranges);
     30 	for (const rd => new_table_reader(&rd, true)!) {
     31 		match (arange_match(&rd, addr)) {
     32 		case void => void;
     33 		case let u: u64 =>
     34 			return u;
     35 		case io::error =>
     36 			return errors::invalid;
     37 		};
     38 	};
     39 };
     40 
     41 fn arange_match(rd: *table_reader, addr: uintptr) (u64 | void | io::error) = {
     42 	const ver = read_uhalf(rd)?;
     43 	const info_offset = read_secword(rd)?;
     44 	const asize = read_ubyte(rd)?;
     45 	const ssize = read_ubyte(rd)?;
     46 	assert(ver == ARANGES_VERSION, "debug::dwarf: unsupported .debug_ranges version");
     47 	assert(ssize == 0, "debug::dwarf: unsupported segmented target for .debug_aranges");
     48 	assert(asize == 8, "debug::dwarf: unsupported address size for .debug_aranges");
     49 
     50 	read_align(rd, asize * 2)?;
     51 
     52 	const au64 = addr: u64;
     53 	for (!read_iseof(rd)) {
     54 		const min = read_ulong(rd)?;
     55 		const length = read_ulong(rd)?;
     56 		if (min == 0 && length == 0) {
     57 			if (!read_iseof(rd)) {
     58 				return errors::invalid;
     59 			};
     60 			break;
     61 		};
     62 		const max = min + length;
     63 		if (min <= au64 && max > au64) {
     64 			return info_offset;
     65 		};
     66 	};
     67 };