summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/lib/libelf/elf64.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/lib/libelf/elf64.c')
-rw-r--r--qemu/roms/SLOF/lib/libelf/elf64.c473
1 files changed, 0 insertions, 473 deletions
diff --git a/qemu/roms/SLOF/lib/libelf/elf64.c b/qemu/roms/SLOF/lib/libelf/elf64.c
deleted file mode 100644
index 37e9c10a9..000000000
--- a/qemu/roms/SLOF/lib/libelf/elf64.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation
- * All rights reserved.
- * This program and the accompanying materials
- * are made available under the terms of the BSD License
- * which accompanies this distribution, and is available at
- * http://www.opensource.org/licenses/bsd-license.php
- *
- * Contributors:
- * IBM Corporation - initial implementation
- *****************************************************************************/
-
-/*
- * 64-bit ELF loader for PowerPC.
- * See the "64-bit PowerPC ELF Application Binary Interface Supplement" and
- * the "ELF-64 Object File Format" documentation for details.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <libelf.h>
-#include <byteorder.h>
-
-struct ehdr64
-{
- uint32_t ei_ident;
- uint8_t ei_class;
- uint8_t ei_data;
- uint8_t ei_version;
- uint8_t ei_pad[9];
- uint16_t e_type;
- uint16_t e_machine;
- uint32_t e_version;
- uint64_t e_entry;
- uint64_t e_phoff;
- uint64_t e_shoff;
- uint32_t e_flags;
- uint16_t e_ehsize;
- uint16_t e_phentsize;
- uint16_t e_phnum;
- uint16_t e_shentsize;
- uint16_t e_shnum;
- uint16_t e_shstrndx;
-};
-
-struct phdr64
-{
- uint32_t p_type;
- uint32_t p_flags;
- uint64_t p_offset;
- uint64_t p_vaddr;
- uint64_t p_paddr;
- uint64_t p_filesz;
- uint64_t p_memsz;
- uint64_t p_align;
-};
-
-struct shdr64
-{
- uint32_t sh_name; /* Section name */
- uint32_t sh_type; /* Section type */
- uint64_t sh_flags; /* Section attributes */
- uint64_t sh_addr; /* Virtual address in memory */
- uint64_t sh_offset; /* Offset in file */
- uint64_t sh_size; /* Size of section */
- uint32_t sh_link; /* Link to other section */
- uint32_t sh_info; /* Miscellaneous information */
- uint64_t sh_addralign; /* Address alignment boundary */
- uint64_t sh_entsize; /* Size of entries, if section has table */
-};
-
-struct rela /* RelA relocation table entry */
-{
- uint64_t r_offset; /* Address of reference */
- uint64_t r_info; /* Symbol index and type of relocation */
- int64_t r_addend; /* Constant part of expression */
-};
-
-struct sym64
-{
- uint32_t st_name; /* Symbol name */
- uint8_t st_info; /* Type and Binding attributes */
- uint8_t st_other; /* Reserved */
- uint16_t st_shndx; /* Section table index */
- uint64_t st_value; /* Symbol value */
- uint64_t st_size; /* Size of object (e.g., common) */
-};
-
-
-/* For relocations */
-#define ELF_R_SYM(i) ((i)>>32)
-#define ELF_R_TYPE(i) ((uint32_t)(i) & 0xFFFFFFFF)
-#define ELF_R_INFO(s,t) ((((uint64_t) (s)) << 32) + (t))
-
-/*
- * Relocation types for PowerPC64.
- */
-#define R_PPC64_NONE 0
-#define R_PPC64_ADDR32 1
-#define R_PPC64_ADDR24 2
-#define R_PPC64_ADDR16 3
-#define R_PPC64_ADDR16_LO 4
-#define R_PPC64_ADDR16_HI 5
-#define R_PPC64_ADDR16_HA 6
-#define R_PPC64_ADDR14 7
-#define R_PPC64_ADDR14_BRTAKEN 8
-#define R_PPC64_ADDR14_BRNTAKEN 9
-#define R_PPC64_REL24 10
-#define R_PPC64_REL14 11
-#define R_PPC64_REL14_BRTAKEN 12
-#define R_PPC64_REL14_BRNTAKEN 13
-#define R_PPC64_GOT16 14
-#define R_PPC64_GOT16_LO 15
-#define R_PPC64_GOT16_HI 16
-#define R_PPC64_GOT16_HA 17
-#define R_PPC64_COPY 19
-#define R_PPC64_GLOB_DAT 20
-#define R_PPC64_JMP_SLOT 21
-#define R_PPC64_RELATIVE 22
-#define R_PPC64_UADDR32 24
-#define R_PPC64_UADDR16 25
-#define R_PPC64_REL32 26
-#define R_PPC64_PLT32 27
-#define R_PPC64_PLTREL32 28
-#define R_PPC64_PLT16_LO 29
-#define R_PPC64_PLT16_HI 30
-#define R_PPC64_PLT16_HA 31
-#define R_PPC64_SECTOFF 33
-#define R_PPC64_SECTOFF_LO 34
-#define R_PPC64_SECTOFF_HI 35
-#define R_PPC64_SECTOFF_HA 36
-#define R_PPC64_ADDR30 37
-#define R_PPC64_ADDR64 38
-#define R_PPC64_ADDR16_HIGHER 39
-#define R_PPC64_ADDR16_HIGHERA 40
-#define R_PPC64_ADDR16_HIGHEST 41
-#define R_PPC64_ADDR16_HIGHESTA 42
-#define R_PPC64_UADDR64 43
-#define R_PPC64_REL64 44
-#define R_PPC64_PLT64 45
-#define R_PPC64_PLTREL64 46
-#define R_PPC64_TOC16 47
-#define R_PPC64_TOC16_LO 48
-#define R_PPC64_TOC16_HI 49
-#define R_PPC64_TOC16_HA 50
-#define R_PPC64_TOC 51
-#define R_PPC64_PLTGOT16 52
-#define R_PPC64_PLTGOT16_LO 53
-#define R_PPC64_PLTGOT16_HI 54
-#define R_PPC64_PLTGOT16_HA 55
-#define R_PPC64_ADDR16_DS 56
-#define R_PPC64_ADDR16_LO_DS 57
-#define R_PPC64_GOT16_DS 58
-#define R_PPC64_GOT16_LO_DS 59
-#define R_PPC64_PLT16_LO_DS 60
-#define R_PPC64_SECTOFF_DS 61
-#define R_PPC64_SECTOFF_LO_DS 62
-#define R_PPC64_TOC16_DS 63
-#define R_PPC64_TOC16_LO_DS 64
-#define R_PPC64_PLTGOT16_DS 65
-#define R_PPC64_PLTGOT16_LO_DS 66
-#define R_PPC64_TLS 67
-#define R_PPC64_DTPMOD64 68
-#define R_PPC64_TPREL16 69
-#define R_PPC64_TPREL16_LO 60
-#define R_PPC64_TPREL16_HI 71
-#define R_PPC64_TPREL16_HA 72
-#define R_PPC64_TPREL64 73
-#define R_PPC64_DTPREL16 74
-#define R_PPC64_DTPREL16_LO 75
-#define R_PPC64_DTPREL16_HI 76
-#define R_PPC64_DTPREL16_HA 77
-#define R_PPC64_DTPREL64 78
-#define R_PPC64_GOT_TLSGD16 79
-#define R_PPC64_GOT_TLSGD16_LO 80
-#define R_PPC64_GOT_TLSGD16_HI 81
-#define R_PPC64_GOT_TLSGD16_HA 82
-#define R_PPC64_GOT_TLSLD16 83
-#define R_PPC64_GOT_TLSLD16_LO 84
-#define R_PPC64_GOT_TLSLD16_HI 85
-#define R_PPC64_GOT_TLSLD16_HA 86
-#define R_PPC64_GOT_TPREL16_DS 87
-#define R_PPC64_GOT_TPREL16_LO_ DS 88
-#define R_PPC64_GOT_TPREL16_HI 89
-#define R_PPC64_GOT_TPREL16_HA 90
-#define R_PPC64_GOT_DTPREL16_DS 91
-#define R_PPC64_GOT_DTPREL16_LO_DS 92
-#define R_PPC64_GOT_DTPREL16_HI 93
-#define R_PPC64_GOT_DTPREL16_HA 94
-#define R_PPC64_TPREL16_DS 95
-#define R_PPC64_TPREL16_LO_DS 96
-#define R_PPC64_TPREL16_HIGHER 97
-#define R_PPC64_TPREL16_HIGHERA 98
-#define R_PPC64_TPREL16_HIGHEST 99
-#define R_PPC64_TPREL16_HIGHESTA 100
-#define R_PPC64_DTPREL16_DS 101
-#define R_PPC64_DTPREL16_LO_DS 102
-#define R_PPC64_DTPREL16_HIGHER 103
-#define R_PPC64_DTPREL16_HIGHERA 104
-#define R_PPC64_DTPREL16_HIGHEST 105
-#define R_PPC64_DTPREL16_HIGHESTA 106
-
-
-static struct phdr64*
-get_phdr64(unsigned long *file_addr)
-{
- return (struct phdr64 *) (((unsigned char *) file_addr)
- + ((struct ehdr64 *)file_addr)->e_phoff);
-}
-
-static void
-load_segment64(unsigned long *file_addr, struct phdr64 *phdr, signed long offset,
- int (*pre_load)(void*, long),
- void (*post_load)(void*, long))
-{
- unsigned long src = phdr->p_offset + (unsigned long) file_addr;
- unsigned long destaddr;
-
- destaddr = phdr->p_paddr + offset;
-
- /* check if we're allowed to copy */
- if (pre_load != NULL) {
- if (pre_load((void*)destaddr, phdr->p_memsz) != 0)
- return;
- }
-
- /* copy into storage */
- memmove((void*)destaddr, (void*)src, phdr->p_filesz);
-
- /* clear bss */
- memset((void*)(destaddr + phdr->p_filesz), 0,
- phdr->p_memsz - phdr->p_filesz);
-
- if (phdr->p_memsz && post_load != NULL) {
- post_load((void*)destaddr, phdr->p_memsz);
- }
-}
-
-unsigned long
-elf_load_segments64(void *file_addr, signed long offset,
- int (*pre_load)(void*, long),
- void (*post_load)(void*, long))
-{
- struct ehdr64 *ehdr = (struct ehdr64 *) file_addr;
- /* Calculate program header address */
- struct phdr64 *phdr = get_phdr64(file_addr);
- int i;
-
- /* loop e_phnum times */
- for (i = 0; i <= ehdr->e_phnum; i++) {
- /* PT_LOAD ? */
- if (phdr->p_type == PT_LOAD) {
- if (phdr->p_paddr != phdr->p_vaddr) {
- printf("ELF64: VirtAddr(%lx) != PhysAddr(%lx) not supported, aborting\n",
- (long)phdr->p_vaddr, (long)phdr->p_paddr);
- return 0;
- }
-
- /* copy segment */
- load_segment64(file_addr, phdr, offset, pre_load, post_load);
- }
- /* step to next header */
- phdr = (struct phdr64 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
- }
-
- /* Entry point is always a virtual address, so translate it
- * to physical before returning it */
- return ehdr->e_entry;
-}
-
-/**
- * Return the base address for loading (i.e. the address of the first PT_LOAD
- * segment)
- * @param file_addr pointer to the ELF file in memory
- * @return the base address
- */
-long
-elf_get_base_addr64(void *file_addr)
-{
- struct ehdr64 *ehdr = (struct ehdr64 *) file_addr;
- /* Calculate program header address */
- struct phdr64 *phdr = get_phdr64(file_addr);
- int i;
-
- /* loop e_phnum times */
- for (i = 0; i <= ehdr->e_phnum; i++) {
- /* PT_LOAD ? */
- if (phdr->p_type == PT_LOAD) {
- /* Return base address */
- return phdr->p_paddr;
- }
- /* step to next header */
- phdr = (struct phdr64 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
- }
-
- return 0;
-}
-
-
-/**
- * Apply one relocation entry.
- */
-static void
-elf_apply_rela64(void *file_addr, signed long offset, struct rela *relaentry,
- struct sym64 *symtabentry)
-{
- void *addr;
- unsigned long s_a;
- unsigned long base_addr;
-
- base_addr = elf_get_base_addr64(file_addr);
-
- /* Sanity check */
- if (relaentry->r_offset < base_addr) {
- printf("\nELF relocation out of bounds!\n");
- return;
- }
-
- base_addr += offset;
-
- /* Actual address where the relocation will be applied at. */
- addr = (void*)(relaentry->r_offset + offset);
-
- /* Symbol value (S) + Addend (A) */
- s_a = symtabentry->st_value + offset + relaentry->r_addend;
-
- switch (ELF_R_TYPE(relaentry->r_info)) {
- case R_PPC64_ADDR32: /* S + A */
- *(uint32_t *)addr = (uint32_t) s_a;
- break;
- case R_PPC64_ADDR64: /* S + A */
- *(uint64_t *)addr = (uint64_t) s_a;
- break;
- case R_PPC64_TOC: /* .TOC */
- *(uint64_t *)addr += offset;
- break;
- case R_PPC64_ADDR16_HIGHEST: /* #highest(S + A) */
- *(uint16_t *)addr = ((s_a >> 48) & 0xffff);
- break;
- case R_PPC64_ADDR16_HIGHER: /* #higher(S + A) */
- *(uint16_t *)addr = ((s_a >> 32) & 0xffff);
- break;
- case R_PPC64_ADDR16_HI: /* #hi(S + A) */
- *(uint16_t *)addr = ((s_a >> 16) & 0xffff);
- break;
- case R_PPC64_ADDR16_LO: /* #lo(S + A) */
- *(uint16_t *)addr = s_a & 0xffff;
- break;
- case R_PPC64_ADDR16_LO_DS:
- *(uint16_t *)addr = (s_a & 0xfffc);
- break;
- case R_PPC64_ADDR16_HA: /* #ha(S + A) */
- *(uint16_t *)addr = (((s_a >> 16) + ((s_a & 0x8000) ? 1 : 0))
- & 0xffff);
- break;
-
- case R_PPC64_TOC16: /* half16* S + A - .TOC. */
- case R_PPC64_TOC16_LO_DS:
- case R_PPC64_TOC16_LO: /* #lo(S + A - .TOC.) */
- case R_PPC64_TOC16_HI: /* #hi(S + A - .TOC.) */
- case R_PPC64_TOC16_HA:
- case R_PPC64_TOC16_DS: /* (S + A - .TOC) >> 2 */
- case R_PPC64_REL14:
- case R_PPC64_REL24: /* (S + A - P) >> 2 */
- case R_PPC64_REL64: /* S + A - P */
- case R_PPC64_GOT16_DS:
- case R_PPC64_GOT16_LO_DS:
- // printf("\t\tignoring relocation type %i\n",
- // ELF_R_TYPE(relaentry->r_info));
- break;
- default:
- printf("ERROR: Unhandled relocation (A) type %i\n",
- ELF_R_TYPE(relaentry->r_info));
- }
-}
-
-
-/**
- * Step through all relocation entries and apply them one by one.
- */
-static void
-elf_apply_all_rela64(void *file_addr, signed long offset, struct shdr64 *shdrs, int idx)
-{
- struct shdr64 *rela_shdr = &shdrs[idx];
- struct shdr64 *dst_shdr = &shdrs[rela_shdr->sh_info];
- struct shdr64 *sym_shdr = &shdrs[rela_shdr->sh_link];
- struct rela *relaentry;
- struct sym64 *symtabentry;
- uint32_t symbolidx;
- int i;
-
- /* If the referenced section has not been allocated, then it has
- * not been loaded and thus does not need to be relocated. */
- if ((dst_shdr->sh_flags & SHF_ALLOC) != SHF_ALLOC)
- return;
-
- for (i = 0; i < rela_shdr->sh_size; i += rela_shdr->sh_entsize) {
- relaentry = (struct rela *)(file_addr + rela_shdr->sh_offset + i);
-
- symbolidx = ELF_R_SYM(relaentry->r_info);
- symtabentry = (struct sym64*)(file_addr + sym_shdr->sh_offset) + symbolidx;
-
- elf_apply_rela64(file_addr, offset, relaentry, symtabentry);
- }
-}
-
-
-/**
- * Apply ELF relocations
- */
-void
-elf_relocate64(void *file_addr, signed long offset)
-{
- struct ehdr64 *ehdr = (struct ehdr64 *) file_addr;
- /* Calculate section header address */
- struct shdr64 *shdrs = (struct shdr64 *)
- (((unsigned char *) file_addr) + ehdr->e_shoff);
- int i;
-
- /* loop over all segments */
- for (i = 0; i <= ehdr->e_shnum; i++) {
- /* Skip if it is not a relocation segment */
- if (shdrs[i].sh_type == SHT_RELA) {
- elf_apply_all_rela64(file_addr, offset, shdrs, i);
- }
- }
-}
-
-void
-elf_byteswap_header64(void *file_addr)
-{
- struct ehdr64 *ehdr = (struct ehdr64 *) file_addr;
- struct phdr64 *phdr;
- int i;
-
- bswap_16p(&ehdr->e_type);
- bswap_16p(&ehdr->e_machine);
- bswap_32p(&ehdr->e_version);
- bswap_64p(&ehdr->e_entry);
- bswap_64p(&ehdr->e_phoff);
- bswap_64p(&ehdr->e_shoff);
- bswap_32p(&ehdr->e_flags);
- bswap_16p(&ehdr->e_ehsize);
- bswap_16p(&ehdr->e_phentsize);
- bswap_16p(&ehdr->e_phnum);
- bswap_16p(&ehdr->e_shentsize);
- bswap_16p(&ehdr->e_shnum);
- bswap_16p(&ehdr->e_shstrndx);
-
- phdr = get_phdr64(file_addr);
-
- /* loop e_phnum times */
- for (i = 0; i <= ehdr->e_phnum; i++) {
- bswap_32p(&phdr->p_type);
- bswap_32p(&phdr->p_flags);
- bswap_64p(&phdr->p_offset);
- bswap_64p(&phdr->p_vaddr);
- bswap_64p(&phdr->p_paddr);
- bswap_64p(&phdr->p_filesz);
- bswap_64p(&phdr->p_memsz);
- bswap_64p(&phdr->p_align);
-
- /* step to next header */
- phdr = (struct phdr64 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
- }
-}
-
-uint32_t elf_get_eflags_64(void *file_addr)
-{
- struct ehdr64 *ehdr = (struct ehdr64 *) file_addr;
-
- return ehdr->e_flags;
-}