We now have text_region and data_region instead of the unclear array.

load_kernel_add_on() now protects the text area read-only (theoretically,
as set_area_protection() has not yet been implemented).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7879 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-06-09 02:55:54 +00:00
parent 9d256ebb6e
commit 577402ea7e
+70 -75
View File
@@ -104,10 +104,10 @@ register_elf_image(struct elf_image_info *image)
imageInfo.type = B_SYSTEM_IMAGE;
strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name));
imageInfo.text = (void *)image->regions[0].start;
imageInfo.text_size = image->regions[0].size;
imageInfo.data = (void *)image->regions[1].start;
imageInfo.data_size = image->regions[1].size;
imageInfo.text = (void *)image->text_region.start;
imageInfo.text_size = image->text_region.size;
imageInfo.data = (void *)image->data_region.start;
imageInfo.data_size = image->data_region.size;
hash_insert(sImagesHash, image);
}
@@ -128,8 +128,8 @@ find_image_at_address(addr_t address)
// get image that may contain the address
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
if (address >= image->regions[0].start
&& address <= (image->regions[0].start + image->regions[0].size))
if (address >= image->text_region.start
&& address <= (image->text_region.start + image->text_region.size))
break;
}
@@ -198,8 +198,8 @@ create_image_struct()
memset(image, 0, sizeof(struct elf_image_info));
image->regions[0].id = -1;
image->regions[1].id = -1;
image->text_region.id = -1;
image->data_region.id = -1;
image->ref_count = 1;
return image;
@@ -271,8 +271,8 @@ dump_symbols(int argc, char **argv)
hash_open(sImagesHash, &iterator);
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
if (image->regions[0].start <= num
&& image->regions[0].start + image->regions[0].size >= num)
if (image->text_region.start <= num
&& image->text_region.start + image->text_region.size >= num)
break;
}
hash_close(sImagesHash, &iterator, false);
@@ -314,10 +314,10 @@ dump_symbols(int argc, char **argv)
struct Elf32_Sym *symbol = &image->debug_symbols[i];
if (symbol->st_value == 0
|| symbol->st_size >= image->regions[0].size + image->regions[1].size)
|| symbol->st_size >= image->text_region.size + image->data_region.size)
continue;
dprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->regions[0].delta,
dprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->text_region.delta,
get_symbol_type_string(symbol), get_symbol_bind_string(symbol), symbol->st_size,
image->debug_string_table + symbol->st_name);
}
@@ -330,10 +330,10 @@ dump_symbols(int argc, char **argv)
struct Elf32_Sym *symbol = &image->syms[j];
if (symbol->st_value == 0
|| symbol->st_size >= image->regions[0].size + image->regions[1].size)
|| symbol->st_size >= image->text_region.size + image->data_region.size)
continue;
dprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->regions[0].delta,
dprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->text_region.delta,
get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
symbol->st_size, SYMNAME(image, symbol));
}
@@ -344,20 +344,24 @@ dump_symbols(int argc, char **argv)
}
static void
dump_elf_region(struct elf_region *region, const char *name)
{
dprintf(" %s.id 0x%lx\n", name, region->id);
dprintf(" %s.start 0x%lx\n", name, region->start);
dprintf(" %s.size 0x%lx\n", name, region->size);
dprintf(" %s.delta %ld\n", name, region->delta);
}
static void
dump_image_info(struct elf_image_info *image)
{
int i;
dprintf("elf_image_info at %p:\n", image);
dprintf(" next %p\n", image->next);
dprintf(" id 0x%lx\n", image->id);
for (i = 0; i < 2; i++) {
dprintf(" regions[%d].id 0x%lx\n", i, image->regions[i].id);
dprintf(" regions[%d].start 0x%lx\n", i, image->regions[i].start);
dprintf(" regions[%d].size 0x%lx\n", i, image->regions[i].size);
dprintf(" regions[%d].delta %ld\n", i, image->regions[i].delta);
}
dump_elf_region(&image->text_region, "text");
dump_elf_region(&image->data_region, "data");
dprintf(" dynamic_ptr 0x%lx\n", image->dynamic_ptr);
dprintf(" needed %p\n", image->needed);
dprintf(" symhash %p\n", image->symhash);
@@ -467,31 +471,31 @@ elf_parse_dynamic_section(struct elf_image_info *image)
for (i = 0; d[i].d_tag != DT_NULL; i++) {
switch (d[i].d_tag) {
case DT_NEEDED:
needed_offset = d[i].d_un.d_ptr + image->regions[0].delta;
needed_offset = d[i].d_un.d_ptr + image->text_region.delta;
break;
case DT_HASH:
image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta);
image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_STRTAB:
image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta);
image->strtab = (char *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_SYMTAB:
image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->regions[0].delta);
image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_REL:
image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_RELSZ:
image->rel_len = d[i].d_un.d_val;
break;
case DT_RELA:
image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->regions[0].delta);
image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_RELASZ:
image->rela_len = d[i].d_un.d_val;
break;
case DT_JMPREL:
image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta);
break;
case DT_PLTRELSZ:
image->pltrel_len = d[i].d_un.d_val;
@@ -554,7 +558,7 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym,
return B_MISSING_SYMBOL;
}
*sym_addr = sym2->st_value + shared_image->regions[0].delta;
*sym_addr = sym2->st_value + shared_image->text_region.delta;
return B_NO_ERROR;
case SHN_ABS:
*sym_addr = sym->st_value;
@@ -565,7 +569,7 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym,
return B_ERROR;
default:
// standard symbol
*sym_addr = sym->st_value + image->regions[0].delta;
*sym_addr = sym->st_value + image->text_region.delta;
return B_NO_ERROR;
}
}
@@ -649,17 +653,14 @@ elf_unlink_relocs(struct elf_image_info *image)
static status_t
unload_elf_image(struct elf_image_info *image)
{
int i;
if (atomic_add(&image->ref_count, -1) > 0)
return B_NO_ERROR;
//elf_unlink_relocs(image);
// not yet used
for (i = 0; i < 2; ++i) {
delete_area(image->regions[i].id);
}
delete_area(image->text_region.id);
delete_area(image->data_region.id);
if (image->vnode)
vfs_put_vnode_ptr(image->vnode);
@@ -792,8 +793,8 @@ insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel)
image->name = strdup(preloadedImage->name);
image->dynamic_ptr = preloadedImage->dynamic_section.start;
image->regions[0] = preloadedImage->text_region;
image->regions[1] = preloadedImage->data_region;
image->text_region = preloadedImage->text_region;
image->data_region = preloadedImage->data_region;
status = elf_parse_dynamic_section(image);
if (status < B_OK)
@@ -857,10 +858,10 @@ get_image_symbol(image_id id, const char *name, int32 sclass, void **_symbol)
// ToDo: support the "sclass" parameter!
TRACE(("found: %lx (%lx + %lx)\n", symbol->st_value + image->regions[0].delta,
symbol->st_value, image->regions[0].delta));
TRACE(("found: %lx (%lx + %lx)\n", symbol->st_value + image->text_region.delta,
symbol->st_value, image->text_region.delta));
*_symbol = (void *)(symbol->st_value + image->regions[0].delta);
*_symbol = (void *)(symbol->st_value + image->text_region.delta);
done:
mutex_unlock(&sImageMutex);
@@ -901,7 +902,7 @@ elf_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_sy
int32 j;
TRACE((" image %p, base = %p, size = %p\n", image,
(void *)image->regions[0].start, (void *)image->regions[0].size));
(void *)image->text_region.start, (void *)image->text_region.size));
if (image->debug_symbols != NULL) {
// search extended debug symbol table (contains static symbols)
@@ -912,10 +913,10 @@ elf_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_sy
struct Elf32_Sym *symbol = &image->debug_symbols[i];
if (symbol->st_value == 0
|| symbol->st_size >= image->regions[0].size + image->regions[1].size)
|| symbol->st_size >= image->text_region.size + image->data_region.size)
continue;
symbolDelta = address - (symbol->st_value + image->regions[0].delta);
symbolDelta = address - (symbol->st_value + image->text_region.delta);
if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
exactMatch = true;
@@ -938,10 +939,10 @@ elf_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_sy
struct Elf32_Sym *symbol = &image->syms[j];
if (symbol->st_value == 0
|| symbol->st_size >= image->regions[0].size + image->regions[1].size)
|| symbol->st_size >= image->text_region.size + image->data_region.size)
continue;
symbolDelta = address - (long)(symbol->st_value + image->regions[0].delta);
symbolDelta = address - (long)(symbol->st_value + image->text_region.delta);
if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
exactMatch = true;
@@ -965,7 +966,7 @@ elf_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_sy
if (_imageName)
*_imageName = image->name;
if (_baseAddress)
*_baseAddress = symbolFound->st_value + image->regions[0].delta;
*_baseAddress = symbolFound->st_value + image->text_region.delta;
if (_exactMatch)
*_exactMatch = exactMatch;
@@ -978,7 +979,7 @@ elf_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_sy
if (_imageName)
*_imageName = image->name;
if (_baseAddress)
*_baseAddress = image->regions[0].start;
*_baseAddress = image->text_region.start;
if (_exactMatch)
*_exactMatch = false;
@@ -1267,8 +1268,7 @@ load_kernel_add_on(const char *path)
for (i = 0; i < eheader->e_phnum; i++) {
char regionName[B_OS_NAME_LENGTH];
int image_region;
int protection;
elf_region *region;
TRACE(("looking at program header %d\n", i));
@@ -1291,8 +1291,8 @@ load_kernel_add_on(const char *path)
continue;
}
rw_segment_handled = true;
image_region = 1;
protection = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA;
region = &image->data_region;
snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", path);
} else if ((pheaders[i].p_flags & (PF_PROTECTION_MASK)) == (PF_READ | PF_EXECUTE)) {
// this is the non-writable segment
@@ -1301,11 +1301,7 @@ load_kernel_add_on(const char *path)
continue;
}
ro_segment_handled = true;
image_region = 0;
protection = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA;
// We need to read in the contents of this area later,
// so it has to be writeable at this point;
// ToDo: we should change the area protection later.
region = &image->text_region;
snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", path);
} else {
@@ -1315,23 +1311,22 @@ load_kernel_add_on(const char *path)
// ToDo: this won't work if the on-disk order of the sections doesn't
// fit the in-memory order...
image->regions[image_region].start = start;
image->regions[image_region].size = ROUNDUP(pheaders[i].p_memsz + (pheaders[i].p_vaddr % PAGE_SIZE), PAGE_SIZE);
image->regions[image_region].id = create_area(regionName,
(void **)&image->regions[image_region].start, B_EXACT_ADDRESS,
image->regions[image_region].size, B_FULL_LOCK, protection);
if (image->regions[image_region].id < 0) {
region->start = start;
region->size = ROUNDUP(pheaders[i].p_memsz + (pheaders[i].p_vaddr % PAGE_SIZE), PAGE_SIZE);
region->id = create_area(regionName, (void **)&region->start, B_EXACT_ADDRESS,
region->size, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (region->id < 0) {
dprintf("error allocating region!\n");
err = B_NOT_AN_EXECUTABLE;
goto error4;
}
image->regions[image_region].delta = image->regions[image_region].start - ROUNDOWN(pheaders[i].p_vaddr, PAGE_SIZE);
start += image->regions[image_region].size;
region->delta = region->start - ROUNDOWN(pheaders[i].p_vaddr, PAGE_SIZE);
start += region->size;
TRACE(("elf_load_kspace: created a region at %p\n", (void *)image->regions[image_region].start));
TRACE(("elf_load_kspace: created a region at %p\n", (void *)region->start));
len = sys_read(fd, pheaders[i].p_offset,
(void *)(image->regions[image_region].start + (pheaders[i].p_vaddr % PAGE_SIZE)),
(void *)(region->start + (pheaders[i].p_vaddr % PAGE_SIZE)),
pheaders[i].p_filesz);
if (len < 0) {
err = len;
@@ -1340,8 +1335,8 @@ load_kernel_add_on(const char *path)
}
}
if (image->regions[1].start != 0
&& image->regions[0].delta != image->regions[1].delta) {
if (image->data_region.start != 0
&& image->text_region.delta != image->data_region.delta) {
dprintf("deltas do not match!\n");
dump_image_info(image);
err = B_ERROR;
@@ -1349,7 +1344,7 @@ load_kernel_add_on(const char *path)
}
// modify the dynamic ptr by the delta of the regions
image->dynamic_ptr += image->regions[0].delta;
image->dynamic_ptr += image->text_region.delta;
err = elf_parse_dynamic_section(image);
if (err < 0)
@@ -1359,7 +1354,9 @@ load_kernel_add_on(const char *path)
if (err < 0)
goto error5;
err = 0;
// We needed to read in the contents of the "text" area, but
// now we can protect it read-only
set_area_protection(image->text_region.id, B_KERNEL_READ_AREA);
// ToDo: this should be enabled by kernel settings!
if (1)
@@ -1376,10 +1373,8 @@ done:
return image->id;
error5:
if (image->regions[1].id >= 0)
delete_area(image->regions[1].id);
if (image->regions[0].id >= 0)
delete_area(image->regions[0].id);
delete_area(image->data_region.id);
delete_area(image->text_region.id);
error4:
vm_unreserve_address_range(vm_get_kernel_aspace_id(), reservedAddress, reservedSize);
error3: