diff --git a/os/src/lib/ldso/arm/platform.c b/os/src/lib/ldso/arm/platform.c index 9cd99da56d..bd3ed56a44 100644 --- a/os/src/lib/ldso/arm/platform.c +++ b/os/src/lib/ldso/arm/platform.c @@ -57,13 +57,10 @@ static void platform_section(Elf_Phdr *phdr, void **priv) */ static void find_exidx(Obj_Entry *obj) { - char buf[PAGE_SIZE]; + char *phdr = file_phdr(obj->path, (void *)obj->mapbase); - int fd = open(obj->path, 0); - read(fd, buf, PAGE_SIZE); - - Elf_Ehdr *ehdr = (Elf_Ehdr *)buf; - Elf_Phdr *ph_table = (Elf_Phdr *)(buf + ehdr->e_phoff); + Elf_Ehdr *ehdr = (Elf_Ehdr *)phdr; + Elf_Phdr *ph_table = (Elf_Phdr *)(phdr + ehdr->e_phoff); unsigned i; size_t start = ~0; diff --git a/os/src/lib/ldso/file.cc b/os/src/lib/ldso/file.cc index 1d33d54f8d..bb8fd9ee53 100644 --- a/os/src/lib/ldso/file.cc +++ b/os/src/lib/ldso/file.cc @@ -110,24 +110,26 @@ namespace Genode { { private: + addr_t _phdr; addr_t _vaddr; /* image start */ addr_t _daddr; /* data start */ Rom_dataspace_capability _ds_rom; /* image ds */ Ram_dataspace_capability _ds_ram; /* data ds */ int _fd; /* file handle */ + Session_capability _rom_cap; public: - enum { - ENOT_FOUND = 1 - }; - - Fd_handle(int fd, Rom_dataspace_capability ds_rom) - : _vaddr(~0UL), _ds_rom(ds_rom), _fd(fd) - {} + Fd_handle(int fd, Rom_dataspace_capability ds_rom, Session_capability rom_cap) + : _vaddr(~0UL), _ds_rom(ds_rom), _fd(fd), _rom_cap(rom_cap) + { + _phdr = (addr_t)env()->rm_session()->attach(_ds_rom, PAGE_SIZE); + } addr_t vaddr() { return _vaddr; } + void vaddr(addr_t vaddr) { _vaddr = vaddr; } Rom_dataspace_capability dataspace() { return _ds_rom; } + addr_t phdr() { return _phdr; } void setup_data(addr_t vaddr, addr_t vlimit, addr_t flimit, off_t offset) { @@ -166,16 +168,20 @@ namespace Genode { return &_file_list; } - static Fd_handle *find_handle(int fd) + static Fd_handle *find_handle(int fd, addr_t vaddr = 0) { Fd_handle *h = file_list()->first(); while (h) { + + if (vaddr && vaddr == h->_vaddr) + return h; if (h->_fd == fd) return h; h = h->next(); } - throw ENOT_FOUND; + + return 0; } static void free(void *addr) @@ -205,7 +211,11 @@ namespace Genode { Rm_area::r()->detach(_daddr); Rm_area::r()->free_region(_vaddr); env()->ram_session()->free(_ds_ram); + env()->rm_session()->detach(_phdr); } + + if (_rom_cap.valid()) + env()->parent()->close(_rom_cap); } }; } @@ -215,6 +225,8 @@ extern "C" int open(const char *pathname, int flags) { using namespace Genode; static int fd = -1; + static int i = 0; + i++; /* skip directory part from pathname, leaving only the plain filename */ const char *filename = pathname; @@ -228,14 +240,34 @@ extern "C" int open(const char *pathname, int flags) rom.on_destruction(Rom_connection::KEEP_OPEN); Fd_handle::file_list()->insert(new(env()->heap()) - Fd_handle(++fd, rom.dataspace())); - return fd; - } - catch (...) { - PERR("Could not open %s\n", filename); + Fd_handle(++fd, rom.dataspace(), rom.cap())); + + Fd_handle *h; + if (!(h = Fd_handle::find_handle(fd))) { + PERR("Could not open %s\n", filename); + return -1; + } + } catch (...) { + PERR("Rom connection failed for %s", filename); + return -1; } - return -1; + return fd; +} + + +extern "C" void *file_phdr(const char *pathname, void *vaddr) +{ + using namespace Genode; + + Fd_handle *h = 0; + if (!(h = Fd_handle::find_handle(-1, (addr_t)vaddr))) { + int fd = open(pathname, 0); + h = Fd_handle::find_handle(fd); + h->vaddr((addr_t)vaddr); + } + + return (void *)h->phdr(); } @@ -244,10 +276,7 @@ extern "C" int find_binary_name(int fd, char *buf, size_t buf_size) using namespace Genode; Fd_handle *h; - try { - h = Fd_handle::find_handle(fd); - } - catch (...) { + if (!(h = Fd_handle::find_handle(fd))) { PERR("handle not found\n"); return -1; } @@ -261,10 +290,8 @@ extern "C" ssize_t read(int fd, void *buf, size_t count) using namespace Genode; Fd_handle *h; - try { - h = Fd_handle::find_handle(fd); - } - catch (...) { + + if (!(h = Fd_handle::find_handle(fd))) { PERR("handle not found\n"); return -1; } @@ -352,8 +379,7 @@ extern "C" void *genode_map(int fd, Elf_Phdr **segs) } Fd_handle *h; - try { h = Fd_handle::find_handle(fd); } - catch (...) { + if (!(h = Fd_handle::find_handle(fd))) { PERR("handle not found\n"); return MAP_FAILED; } diff --git a/os/src/lib/ldso/include/libc_emu/unistd.h b/os/src/lib/ldso/include/libc_emu/unistd.h index 15b7c5b7bb..9b7e0e4018 100644 --- a/os/src/lib/ldso/include/libc_emu/unistd.h +++ b/os/src/lib/ldso/include/libc_emu/unistd.h @@ -31,6 +31,8 @@ int issetugid(void) { return 1; } static inline int close(int fd) { return 0; } +void *file_phdr(const char *, void *); + enum whence { SEEK_SET };