base-common: copy all sparse ELF segments, including read-only

This commit is contained in:
Ehmry - 2019-09-28 14:31:53 +02:00
parent 5e87eee9b8
commit d348e96b84
1 changed files with 19 additions and 12 deletions

View File

@ -68,9 +68,11 @@ Child::Process::Loaded_executable::Loaded_executable(Type type,
bool const write = seg.flags().w;
bool const exec = seg.flags().x;
if (write) {
Dataspace_capability ds_cap = ldso_ds;
off_t offset = 0;
/* read-write segment */
if (write || seg.file_size() < seg.mem_size()) {
/* segment must be copied */
/*
* Note that a failure to allocate a RAM dataspace after other
@ -83,10 +85,9 @@ Child::Process::Loaded_executable::Loaded_executable(Type type,
*/
/* alloc dataspace */
Dataspace_capability ds_cap;
try { ds_cap = ram.alloc(size); }
catch (Out_of_ram) {
error("allocation of read-write segment failed"); throw; };
error("allocation of ELF segment failed"); throw; };
/* attach dataspace */
void *base;
@ -117,26 +118,32 @@ Child::Process::Loaded_executable::Loaded_executable(Type type,
/* detach dataspace */
local_rm.detach(base);
off_t const offset = 0;
try { remote_rm.attach_at(ds_cap, addr, size, offset); }
try {
if (exec)
remote_rm.attach_executable(ds_cap, addr, size, offset);
else
remote_rm.attach_at(ds_cap, addr, size, offset);
}
catch (Region_map::Region_conflict) {
error("region conflict while remotely attaching ELF segment");
error("addr=", (void *)addr, " size=", (void *)size, " offset=", (void *)offset);
throw; }
} else {
/* read-only segment */
offset = seg.file_offset();
if (seg.file_size() != seg.mem_size())
warning("filesz and memsz for read-only segment differ");
if (!ds_cap.valid())
Genode::error("segment dataspace is not valid");
if (!Dataspace_client(ds_cap).size())
Genode::error("segment dataspace is zero sized");
off_t const offset = seg.file_offset();
try {
if (exec)
remote_rm.attach_executable(ldso_ds, addr, size, offset);
remote_rm.attach_executable(ds_cap, addr, size, offset);
else
remote_rm.attach_at(ldso_ds, addr, size, offset);
remote_rm.attach_at(ds_cap, addr, size, offset);
}
catch (Region_map::Region_conflict) {
error("region conflict while remotely attaching read-only ELF segment");