hare

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

sections.ha (2649B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use format::elf;
      5 use format::elf::{sht};
      6 use types::c;
      7 use memio;
      8 
      9 // Check that this section is actually a reference to this image.
     10 fn section_validate(image: *image, sec: *elf::section64) void = {
     11 	const addr = sec: uintptr;
     12 	const min = &image.data[0]: uintptr;
     13 	const max = min + len(image.data): uintptr;
     14 	assert(min <= addr && max > addr, "section_name: invalid section");
     15 };
     16 
     17 // Returns a program section by name. Returns null if there is no such section,
     18 // or if the section names are not available in this image (e.g. because it was
     19 // stripped).
     20 export fn section_byname(
     21 	image: *image,
     22 	name: str,
     23 ) nullable *elf::section64 = {
     24 	const cached = [
     25 		(".symtab", &image.symtab),
     26 		(".strtab", &image.strtab),
     27 		(".debug_abbr", &image.debug_abbr),
     28 		(".debug_aranges", &image.debug_aranges),
     29 		(".debug_info", &image.debug_info),
     30 		(".debug_line", &image.debug_line),
     31 		(".debug_str", &image.debug_str),
     32 	];
     33 	for (const (cand, val) .. cached) {
     34 		if (cand == name) {
     35 			match (*val) {
     36 			case null => break;
     37 			case let sec: *elf::section64 =>
     38 				return sec;
     39 			};
     40 		};
     41 	};
     42 
     43 	const head = image.header;
     44 	let r: nullable *elf::section64 = null;
     45 	for (let i = 0u16; i < head.e_shnum; i += 1) {
     46 		const shoffs = head.e_shoff + i * head.e_shentsize;
     47 		const sec = &image.data[shoffs]: *elf::section64;
     48 		if (sec.sh_type == sht::NULL) {
     49 			continue;
     50 		};
     51 
     52 		const cand = section_name(image, sec);
     53 		if (cand == name) {
     54 			r = sec;
     55 			break;
     56 		};
     57 	};
     58 
     59 	match (r) {
     60 	case null =>
     61 		return null;
     62 	case let sec: *elf::section64 =>
     63 		for (let (cand, val) .. cached) {
     64 			if (cand == name) {
     65 				*val = sec;
     66 				break;
     67 			};
     68 		};
     69 	};
     70 
     71 	return r;
     72 };
     73 
     74 // Returns the name of this [[elf::section64]], returning "" if the section
     75 // names are not available in this image (i.e. it has been stripped).
     76 export fn section_name(
     77 	image: *image,
     78 	sec: *elf::section64,
     79 ) const str = {
     80 	section_validate(image, sec);
     81 
     82 	const shtab = match (image.shstrtab) {
     83 	case let sec: *elf::section64 =>
     84 		yield sec;
     85 	case null =>
     86 		return "";
     87 	};
     88 
     89 	const offs = shtab.sh_offset + sec.sh_name;
     90 	return c::tostr(&image.data[offs]: *const c::char)!;
     91 };
     92 
     93 // Returns a slice of the data contained with a given section.
     94 export fn section_data(image: *image, sec: *elf::section64) []u8 = {
     95 	section_validate(image, sec);
     96 	return image.data[sec.sh_offset..sec.sh_offset+sec.sh_size];
     97 };
     98 
     99 // Returns a [[memio::fixed]] reader for the given section.
    100 export fn section_reader(image: *image, sec: *elf::section64) memio::stream = {
    101 	const data = section_data(image, sec);
    102 	return memio::fixed(data);
    103 };