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 13struct elf_load_info { 14 elf_load_header_t header; 15 elf_phdr_t phdrs[]; 16}; 17 18void elf_load_destroy(elf_load_info_t* info) { 19 free(info); 20} 21 22zx_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 44zx_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 64zx_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 72size_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