kernel/elf: Use Deleters and get rid of gotos in elf_load_user_image.
Briefly tested: system boots and applications launch as before.
This commit is contained in:
parent
64a051399f
commit
b6bfd9b749
@ -37,6 +37,7 @@
|
|||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <runtime_loader.h>
|
#include <runtime_loader.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
|
#include <StackOrHeapArray.h>
|
||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_types.h>
|
#include <vm/vm_types.h>
|
||||||
@ -1826,21 +1827,16 @@ status_t
|
|||||||
elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
||||||
{
|
{
|
||||||
elf_ehdr elfHeader;
|
elf_ehdr elfHeader;
|
||||||
elf_phdr *programHeaders = NULL;
|
|
||||||
char baseName[B_OS_NAME_LENGTH];
|
char baseName[B_OS_NAME_LENGTH];
|
||||||
status_t status;
|
status_t status;
|
||||||
ssize_t length;
|
ssize_t length;
|
||||||
int fd;
|
|
||||||
int i;
|
|
||||||
addr_t delta = 0;
|
|
||||||
uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
|
|
||||||
area_id* mappedAreas = NULL;
|
|
||||||
|
|
||||||
TRACE(("elf_load: entry path '%s', team %p\n", path, team));
|
TRACE(("elf_load: entry path '%s', team %p\n", path, team));
|
||||||
|
|
||||||
fd = _kern_open(-1, path, O_RDONLY, 0);
|
int fd = _kern_open(-1, path, O_RDONLY, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
FileDescriptorCloser fdCloser(fd);
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
|
status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
|
||||||
@ -1850,19 +1846,16 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
// read and verify the ELF header
|
// read and verify the ELF header
|
||||||
|
|
||||||
length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
|
length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
|
||||||
if (length < B_OK) {
|
if (length < B_OK)
|
||||||
status = length;
|
return length;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length != sizeof(elfHeader)) {
|
if (length != sizeof(elfHeader)) {
|
||||||
// short read
|
// short read
|
||||||
status = B_NOT_AN_EXECUTABLE;
|
return B_NOT_AN_EXECUTABLE;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
status = verify_eheader(&elfHeader);
|
status = verify_eheader(&elfHeader);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto error;
|
return status;
|
||||||
|
|
||||||
#ifdef ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE
|
#ifdef ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE
|
||||||
if ((flags & ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE) != 0)
|
if ((flags & ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE) != 0)
|
||||||
@ -1871,35 +1864,45 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
|
|
||||||
struct elf_image_info* image;
|
struct elf_image_info* image;
|
||||||
image = create_image_struct();
|
image = create_image_struct();
|
||||||
if (image == NULL) {
|
if (image == NULL)
|
||||||
status = B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
goto error;
|
CObjectDeleter<elf_image_info, void, delete_elf_image> imageDeleter(image);
|
||||||
}
|
|
||||||
|
struct ElfHeaderUnsetter {
|
||||||
|
ElfHeaderUnsetter(elf_image_info* image)
|
||||||
|
: fImage(image)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~ElfHeaderUnsetter()
|
||||||
|
{
|
||||||
|
fImage->elf_header = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
elf_image_info* fImage;
|
||||||
|
} headerUnsetter(image);
|
||||||
image->elf_header = &elfHeader;
|
image->elf_header = &elfHeader;
|
||||||
|
|
||||||
// read program header
|
// read program header
|
||||||
|
|
||||||
programHeaders = (elf_phdr *)malloc(
|
elf_phdr *programHeaders = (elf_phdr *)malloc(
|
||||||
elfHeader.e_phnum * elfHeader.e_phentsize);
|
elfHeader.e_phnum * elfHeader.e_phentsize);
|
||||||
if (programHeaders == NULL) {
|
if (programHeaders == NULL) {
|
||||||
dprintf("error allocating space for program headers\n");
|
dprintf("error allocating space for program headers\n");
|
||||||
status = B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
goto error2;
|
|
||||||
}
|
}
|
||||||
|
MemoryDeleter headersDeleter(programHeaders);
|
||||||
|
|
||||||
TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
|
TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
|
||||||
elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
|
elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
|
||||||
length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
|
length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
|
||||||
elfHeader.e_phnum * elfHeader.e_phentsize);
|
elfHeader.e_phnum * elfHeader.e_phentsize);
|
||||||
if (length < B_OK) {
|
if (length < B_OK) {
|
||||||
status = length;
|
|
||||||
dprintf("error reading in program headers\n");
|
dprintf("error reading in program headers\n");
|
||||||
goto error2;
|
return length;
|
||||||
}
|
}
|
||||||
if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
|
if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
|
||||||
dprintf("short read while reading in program headers\n");
|
dprintf("short read while reading in program headers\n");
|
||||||
status = -1;
|
return B_ERROR;
|
||||||
goto error2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct a nice name for the region we have to create below
|
// construct a nice name for the region we have to create below
|
||||||
@ -1922,16 +1925,16 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
// map the program's segments into memory, initially with rw access
|
// map the program's segments into memory, initially with rw access
|
||||||
// correct area protection will be set after relocation
|
// correct area protection will be set after relocation
|
||||||
|
|
||||||
mappedAreas = (area_id*)malloc(sizeof(area_id) * elfHeader.e_phnum);
|
BStackOrHeapArray<area_id, 8> mappedAreas(elfHeader.e_phnum);
|
||||||
if (mappedAreas == NULL) {
|
if (!mappedAreas.IsValid())
|
||||||
status = B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
goto error2;
|
|
||||||
}
|
|
||||||
|
|
||||||
extended_image_info imageInfo;
|
extended_image_info imageInfo;
|
||||||
memset(&imageInfo, 0, sizeof(imageInfo));
|
memset(&imageInfo, 0, sizeof(imageInfo));
|
||||||
|
|
||||||
for (i = 0; i < elfHeader.e_phnum; i++) {
|
addr_t delta = 0;
|
||||||
|
uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
|
||||||
|
for (int i = 0; i < elfHeader.e_phnum; i++) {
|
||||||
char regionName[B_OS_NAME_LENGTH];
|
char regionName[B_OS_NAME_LENGTH];
|
||||||
char *regionAddress;
|
char *regionAddress;
|
||||||
char *originalRegionAddress;
|
char *originalRegionAddress;
|
||||||
@ -1969,8 +1972,7 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
|
fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
|
||||||
if (id < B_OK) {
|
if (id < B_OK) {
|
||||||
dprintf("error mapping file data: %s!\n", strerror(id));
|
dprintf("error mapping file data: %s!\n", strerror(id));
|
||||||
status = B_NOT_AN_EXECUTABLE;
|
return B_NOT_AN_EXECUTABLE;
|
||||||
goto error2;
|
|
||||||
}
|
}
|
||||||
mappedAreas[i] = id;
|
mappedAreas[i] = id;
|
||||||
|
|
||||||
@ -2010,8 +2012,7 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
&physicalRestrictions, (void**)®ionAddress);
|
&physicalRestrictions, (void**)®ionAddress);
|
||||||
if (id < B_OK) {
|
if (id < B_OK) {
|
||||||
dprintf("error allocating bss area: %s!\n", strerror(id));
|
dprintf("error allocating bss area: %s!\n", strerror(id));
|
||||||
status = B_NOT_AN_EXECUTABLE;
|
return B_NOT_AN_EXECUTABLE;
|
||||||
goto error2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2027,8 +2028,7 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
|
ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
|
||||||
if (id < B_OK) {
|
if (id < B_OK) {
|
||||||
dprintf("error mapping file text: %s!\n", strerror(id));
|
dprintf("error mapping file text: %s!\n", strerror(id));
|
||||||
status = B_NOT_AN_EXECUTABLE;
|
return B_NOT_AN_EXECUTABLE;
|
||||||
goto error2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mappedAreas[i] = id;
|
mappedAreas[i] = id;
|
||||||
@ -2054,17 +2054,21 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
|
|
||||||
set_ac();
|
set_ac();
|
||||||
status = elf_parse_dynamic_section(image);
|
status = elf_parse_dynamic_section(image);
|
||||||
if (status != B_OK)
|
if (status != B_OK) {
|
||||||
goto error2;
|
clear_ac();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
status = elf_relocate(image, image);
|
status = elf_relocate(image, image);
|
||||||
if (status != B_OK)
|
if (status != B_OK) {
|
||||||
goto error2;
|
clear_ac();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
clear_ac();
|
clear_ac();
|
||||||
|
|
||||||
// set correct area protection
|
// set correct area protection
|
||||||
for (i = 0; i < elfHeader.e_phnum; i++) {
|
for (int i = 0; i < elfHeader.e_phnum; i++) {
|
||||||
if (mappedAreas[i] == -1)
|
if (mappedAreas[i] == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2080,7 +2084,7 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
status = vm_set_area_protection(team->id, mappedAreas[i], protection,
|
status = vm_set_area_protection(team->id, mappedAreas[i], protection,
|
||||||
true);
|
true);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto error2;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the loaded image
|
// register the loaded image
|
||||||
@ -2109,20 +2113,7 @@ elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
|
|||||||
TRACE(("elf_load: done!\n"));
|
TRACE(("elf_load: done!\n"));
|
||||||
|
|
||||||
*entry = elfHeader.e_entry + delta;
|
*entry = elfHeader.e_entry + delta;
|
||||||
status = B_OK;
|
return B_OK;
|
||||||
|
|
||||||
error2:
|
|
||||||
clear_ac();
|
|
||||||
free(mappedAreas);
|
|
||||||
|
|
||||||
image->elf_header = NULL;
|
|
||||||
delete_elf_image(image);
|
|
||||||
|
|
||||||
error:
|
|
||||||
free(programHeaders);
|
|
||||||
_kern_close(fd);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user