1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "elf.h"
6
7 #include <elfload/elfload.h>
8
9 #include <zircon/process.h>
10 #include <zircon/syscalls.h>
11 #include <stdlib.h>
12
13 struct elf_load_info {
14 elf_load_header_t header;
15 elf_phdr_t phdrs[];
16 };
17
elf_load_destroy(elf_load_info_t * info)18 void elf_load_destroy(elf_load_info_t* info) {
19 free(info);
20 }
21
elf_load_start(zx_handle_t vmo,const void * hdr_buf,size_t buf_sz,elf_load_info_t ** infop)22 zx_status_t elf_load_start(zx_handle_t vmo, const void* hdr_buf, size_t buf_sz,
23 elf_load_info_t** infop) {
24 elf_load_header_t header;
25 uintptr_t phoff;
26 zx_status_t status = elf_load_prepare(vmo, hdr_buf, buf_sz, &header, &phoff);
27 if (status == ZX_OK) {
28 // Now allocate the data structure and read in the phdrs.
29 size_t phdrs_size = (size_t)header.e_phnum * sizeof(elf_phdr_t);
30 elf_load_info_t* info = malloc(sizeof(*info) + phdrs_size);
31 if (info == NULL)
32 return ZX_ERR_NO_MEMORY;
33 status = elf_load_read_phdrs(vmo, info->phdrs, phoff, header.e_phnum);
34 if (status == ZX_OK) {
35 info->header = header;
36 *infop = info;
37 } else {
38 free(info);
39 }
40 }
41 return status;
42 }
43
elf_load_get_interp(elf_load_info_t * info,zx_handle_t vmo,char ** interp,size_t * interp_len)44 zx_status_t elf_load_get_interp(elf_load_info_t* info, zx_handle_t vmo,
45 char** interp, size_t* interp_len) {
46 char *buffer = NULL;
47 uintptr_t offset;
48 if (elf_load_find_interp(info->phdrs, info->header.e_phnum,
49 &offset, interp_len)) {
50 buffer = malloc(*interp_len + 1);
51 if (buffer == NULL)
52 return ZX_ERR_NO_MEMORY;
53 zx_status_t status = zx_vmo_read(vmo, buffer, offset, *interp_len);
54 if (status < 0) {
55 free(buffer);
56 return status;
57 }
58 buffer[*interp_len] = '\0';
59 }
60 *interp = buffer;
61 return ZX_OK;
62 }
63
elf_load_finish(zx_handle_t vmar,elf_load_info_t * info,zx_handle_t vmo,zx_handle_t * segments_vmar,zx_vaddr_t * base,zx_vaddr_t * entry)64 zx_status_t elf_load_finish(zx_handle_t vmar, elf_load_info_t* info,
65 zx_handle_t vmo,
66 zx_handle_t* segments_vmar,
67 zx_vaddr_t* base, zx_vaddr_t* entry) {
68 return elf_load_map_segments(vmar, &info->header, info->phdrs, vmo,
69 segments_vmar, base, entry);
70 }
71
elf_load_get_stack_size(elf_load_info_t * info)72 size_t elf_load_get_stack_size(elf_load_info_t* info) {
73 for (uint_fast16_t i = 0; i < info->header.e_phnum; ++i) {
74 if (info->phdrs[i].p_type == PT_GNU_STACK)
75 return info->phdrs[i].p_memsz;
76 }
77 return 0;
78 }
79