From 8c4bb7d84838e8c01673caa8ad45a4c042ccdd11 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Mon, 6 Apr 2020 16:32:13 +0530 Subject: [PATCH] ld: support for loading read-only segments --- repos/base/src/lib/ldso/include/file.h | 24 ++++++++++++++++++-- repos/base/src/lib/ldso/include/region_map.h | 10 ++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/repos/base/src/lib/ldso/include/file.h b/repos/base/src/lib/ldso/include/file.h index 1c9ce53ca3..6688f0edd2 100644 --- a/repos/base/src/lib/ldso/include/file.h +++ b/repos/base/src/lib/ldso/include/file.h @@ -34,6 +34,9 @@ namespace Linker { static inline bool is_rw(Elf::Phdr const &ph) { return ((ph.p_flags & PF_MASK) == (PF_R | PF_W)); } + + static inline bool is_ro(Elf::Phdr const &ph) { + return ((ph.p_flags & PF_MASK) == PF_R); } } @@ -280,15 +283,21 @@ struct Linker::Elf_file : File else if (is_rw(*ph)) load_segment_rw(*ph, i); + else if (is_ro(*ph)) + load_segment_ro(*ph); + else { - error("LD: Non-RW/RX segment"); + auto X = ph->p_flags & PF_X ? "X" : "-"; + auto W = ph->p_flags & PF_W ? "W" : "-"; + auto R = ph->p_flags & PF_R ? "R" : "-"; + error("LD: unhandled ", X,W,R, " segment at file offset ", Hex(ph->p_offset)); throw Invalid_file(); } } } /** - * Map read-only segment + * Map read-execute-only segment */ void load_segment_rx(Elf::Phdr const &p) { @@ -318,6 +327,17 @@ struct Linker::Elf_file : File env.rm().detach(src); } + /** + * Map read-only segment + */ + void load_segment_ro(Elf::Phdr const &p) + { + Region_map::r()->attach_readonly(rom_cap, + trunc_page(p.p_vaddr) + reloc_base, + round_page(p.p_memsz), + trunc_page(p.p_offset)); + } + /** * Unmap segements, RM regions, and free allocated dataspaces */ diff --git a/repos/base/src/lib/ldso/include/region_map.h b/repos/base/src/lib/ldso/include/region_map.h index cbee34c639..b30c2221da 100644 --- a/repos/base/src/lib/ldso/include/region_map.h +++ b/repos/base/src/lib/ldso/include/region_map.h @@ -122,6 +122,16 @@ class Linker::Region_map [&] () { _env.upgrade(Parent::Env::pd(), "ram_quota=8K"); }); } + Local_addr attach_readonly(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) + { + return retry( + [&] () { + return _rm.attach(ds, size, offset, true, local_addr - _base, false, false); + }, + [&] () { _env.upgrade(Parent::Env::pd(), "ram_quota=8K"); }); + } + void detach(Local_addr local_addr) { _rm.detach((addr_t)local_addr - _base); } }; -- 2.28.0