Reworked libelf to support relocation
Split elf.c into elf32.c and elf64.c for better readability. Added relocation code to libelf for 64-bit ELF images, modified the Paflof Makefile to link the executable with relocation information and load Paflof now to the upper end of the memory. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
This commit is contained in:
parent
2e2e4cae37
commit
7a3606eeb9
|
@ -264,7 +264,9 @@ early_c_entry(uint64_t start_addr)
|
|||
load_file(0x100, "xvect", 0, romfs_base);
|
||||
load_file(SLAVELOOP_LOADBASE, "stageS", 0, romfs_base);
|
||||
c_romfs_lookup("ofw_main", romfs_base, &fileInfo);
|
||||
load_elf_file((void *) fileInfo.addr_data, &ofw_addr);
|
||||
|
||||
elf_load_file((void *) fileInfo.addr_data, &ofw_addr,
|
||||
NULL, flush_cache);
|
||||
ofw_start =
|
||||
(void (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))
|
||||
&ofw_addr;
|
||||
|
@ -279,6 +281,7 @@ early_c_entry(uint64_t start_addr)
|
|||
* non-ePAPR-compliant firmware
|
||||
* r7 = implementation dependent
|
||||
*/
|
||||
asm volatile("isync; sync;" : : : "memory");
|
||||
ofw_start(0, romfs_base, 0, 0, 0);
|
||||
// never return
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ void early_c_entry(uint64_t start_addr, uint64_t fdt_addr)
|
|||
struct romfs_lookup_t fileInfo;
|
||||
void (*ofw_start) (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||
uint64_t *boot_info;
|
||||
uint64_t romfs_base;
|
||||
uint64_t romfs_base, paflof_base;
|
||||
// romfs header values
|
||||
struct stH *header = (struct stH *) (start_addr + 0x28);
|
||||
uint64_t flashlen = 0;
|
||||
|
@ -133,9 +133,15 @@ void early_c_entry(uint64_t start_addr, uint64_t fdt_addr)
|
|||
|
||||
flashlen = header->flashlen;
|
||||
|
||||
romfs_base = 0x10000000 - 0x400000;
|
||||
if (romfs_base)
|
||||
memcpy((char *)romfs_base, 0, 0x400000);
|
||||
if (fdt_addr == 0) {
|
||||
puts("ERROR: Flatten device tree available!");
|
||||
}
|
||||
|
||||
/* Hack: Determine base for "ROM filesystem" in memory...
|
||||
* QEMU loads the FDT at the top of the available RAM, so we place
|
||||
* the ROMFS just underneath. */
|
||||
romfs_base = (fdt_addr - 0x410000) & ~0xffffLL;
|
||||
memcpy((char *)romfs_base, 0, 0x400000);
|
||||
|
||||
exception_stack_frame = 0;
|
||||
|
||||
|
@ -157,12 +163,21 @@ void early_c_entry(uint64_t start_addr, uint64_t fdt_addr)
|
|||
DEBUG(" [ofw_main size data 0x%lx]\n", fileInfo.size_data);
|
||||
DEBUG(" [ofw_main flags 0x%lx]\n", fileInfo.flags);
|
||||
DEBUG(" [hdr: 0x%08lx 0x%08lx]\n [ 0x%08lx 0x%08lx]\n",
|
||||
((uint64_t *)fileInfo.addr_header)[0],
|
||||
((uint64_t *)fileInfo.addr_header)[0],
|
||||
((uint64_t *)fileInfo.addr_header)[1],
|
||||
((uint64_t *)fileInfo.addr_header)[2],
|
||||
((uint64_t *)fileInfo.addr_header)[3]);
|
||||
rc = load_elf_file((void *)fileInfo.addr_data, ofw_addr);
|
||||
|
||||
/* Assume that paflof need ca. 16 MiB RAM right now..
|
||||
* TODO: Use value from ELF file instead */
|
||||
paflof_base = romfs_base - 0x1000000 + 0x100;
|
||||
if ((int64_t)paflof_base <= 0LL) {
|
||||
puts("ERROR: Not enough memory for Open Firmware");
|
||||
}
|
||||
rc = elf_load_file_to_addr((void *)fileInfo.addr_data, (void*)paflof_base,
|
||||
ofw_addr, NULL, flush_cache);
|
||||
DEBUG(" [load_elf_file returned %d]\n", rc);
|
||||
|
||||
ofw_start =
|
||||
(void (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))
|
||||
&ofw_addr;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2004, 2008 IBM Corporation
|
||||
* 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
|
||||
|
@ -10,9 +10,79 @@
|
|||
* IBM Corporation - initial implementation
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* ELF loader library
|
||||
*/
|
||||
|
||||
#ifndef __LIBELF_H
|
||||
#define __LIBELF_H
|
||||
|
||||
int load_elf_file(unsigned long *, unsigned long *);
|
||||
#include <stdint.h>
|
||||
|
||||
/* ELF object file types */
|
||||
#define ET_NONE 0 /* No file type */
|
||||
#define ET_REL 1 /* Relocatable file */
|
||||
#define ET_EXEC 2 /* Executable file */
|
||||
#define ET_DYN 3 /* Shared object file */
|
||||
#define ET_CORE 4 /* Core file */
|
||||
|
||||
/* Generic ELF header */
|
||||
struct ehdr {
|
||||
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;
|
||||
};
|
||||
|
||||
/* Section types (sh_type) */
|
||||
#define SHT_NULL 0 /* Unused section header */
|
||||
#define SHT_PROGBITS 1 /* Information defined by the program */
|
||||
#define SHT_SYMTAB 2 /* Linker symbol table */
|
||||
#define SHT_STRTAB 3 /* String table */
|
||||
#define SHT_RELA 4 /* "Rela" type relocation entries */
|
||||
#define SHT_HASH 5 /* Symbol hash table */
|
||||
#define SHT_DYNAMIC 6 /* Dynamic linking tables */
|
||||
#define SHT_NOTE 7 /* Note information */
|
||||
#define SHT_NOBITS 8 /* Uninitialized space */
|
||||
#define SHT_REL 9 /* "Rel" type relocation entries */
|
||||
#define SHT_SHLIB 10 /* Reserved */
|
||||
#define SHT_DYNSYM 11 /* Dynamic loader symbol table */
|
||||
|
||||
/* Section attributs (sh_flags) */
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_ALLOC 0x2
|
||||
#define SHF_EXECINSTR 0x4
|
||||
|
||||
/* Segment types (p_type) */
|
||||
#define PT_NULL 0 /* Unused entry */
|
||||
#define PT_LOAD 1 /* Loadable segment */
|
||||
#define PT_DYNAMIC 2 /* Dynamic linking tables */
|
||||
#define PT_INTERP 3 /* Program interpreter path name */
|
||||
#define PT_NOTE 4 /* Note sections */
|
||||
|
||||
|
||||
int elf_load_file(void *file_addr, unsigned long *entry,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long));
|
||||
int elf_load_file_to_addr(void *file_addr, void *addr, unsigned long *entry,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long));
|
||||
|
||||
unsigned int elf_load_segments32(void *file_addr, signed long offset,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long));
|
||||
unsigned long elf_load_segments64(void *file_addr, signed long offset,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long));
|
||||
|
||||
long elf_get_base_addr(void *file_addr);
|
||||
long elf_get_base_addr32(void *file_addr);
|
||||
long elf_get_base_addr64(void *file_addr);
|
||||
|
||||
void elf_relocate64(void *file_addr, signed long offset);
|
||||
|
||||
#endif /* __LIBELF_H */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# *****************************************************************************
|
||||
# * Copyright (c) 2004, 2008 IBM Corporation
|
||||
# * 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
|
||||
|
@ -21,7 +21,7 @@ TARGET = ../libelf.a
|
|||
|
||||
all: $(TARGET)
|
||||
|
||||
SRCS = elf.c
|
||||
SRCS = elf.c elf32.c elf64.c
|
||||
|
||||
OBJS = $(SRCS:%.c=%.o)
|
||||
|
||||
|
|
249
lib/libelf/elf.c
249
lib/libelf/elf.c
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2004, 2008 IBM Corporation
|
||||
* 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
|
||||
|
@ -10,161 +10,14 @@
|
|||
* IBM Corporation - initial implementation
|
||||
*****************************************************************************/
|
||||
|
||||
/* this is elf.fs rewritten in C */
|
||||
/*
|
||||
* ELF loader
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <cpu.h>
|
||||
#include <cache.h>
|
||||
#include <libelf.h>
|
||||
|
||||
struct ehdr {
|
||||
unsigned int ei_ident;
|
||||
unsigned char ei_class;
|
||||
unsigned char ei_data;
|
||||
unsigned char ei_version;
|
||||
unsigned char ei_pad[9];
|
||||
unsigned short e_type;
|
||||
unsigned short e_machine;
|
||||
unsigned int e_version;
|
||||
unsigned int e_entry;
|
||||
unsigned int e_phoff;
|
||||
unsigned int e_shoff;
|
||||
unsigned int e_flags;
|
||||
unsigned short e_ehsize;
|
||||
unsigned short e_phentsize;
|
||||
unsigned short e_phnum;
|
||||
unsigned short e_shentsize;
|
||||
unsigned short e_shnum;
|
||||
unsigned short e_shstrndx;
|
||||
};
|
||||
|
||||
struct phdr {
|
||||
unsigned int p_type;
|
||||
unsigned int p_offset;
|
||||
unsigned int p_vaddr;
|
||||
unsigned int p_paddr;
|
||||
unsigned int p_filesz;
|
||||
unsigned int p_memsz;
|
||||
unsigned int p_flags;
|
||||
unsigned int p_align;
|
||||
};
|
||||
|
||||
struct ehdr64 {
|
||||
unsigned int ei_ident;
|
||||
unsigned char ei_class;
|
||||
unsigned char ei_data;
|
||||
unsigned char ei_version;
|
||||
unsigned char ei_pad[9];
|
||||
unsigned short e_type;
|
||||
unsigned short e_machine;
|
||||
unsigned int e_version;
|
||||
unsigned long e_entry;
|
||||
unsigned long e_phoff;
|
||||
unsigned long e_shoff;
|
||||
unsigned int e_flags;
|
||||
unsigned short e_ehsize;
|
||||
unsigned short e_phentsize;
|
||||
unsigned short e_phnum;
|
||||
unsigned short e_shentsize;
|
||||
unsigned short e_shnum;
|
||||
unsigned short e_shstrndx;
|
||||
};
|
||||
|
||||
struct phdr64 {
|
||||
unsigned int p_type;
|
||||
unsigned int p_flags;
|
||||
unsigned long p_offset;
|
||||
unsigned long p_vaddr;
|
||||
unsigned long p_paddr;
|
||||
unsigned long p_filesz;
|
||||
unsigned long p_memsz;
|
||||
unsigned long p_align;
|
||||
};
|
||||
|
||||
#define VOID(x) (void *)((unsigned long)x)
|
||||
|
||||
static void
|
||||
load_segment(unsigned long *file_addr, struct phdr *phdr)
|
||||
{
|
||||
unsigned long src = phdr->p_offset + (unsigned long) file_addr;
|
||||
/* copy into storage */
|
||||
memmove(VOID(phdr->p_vaddr), VOID(src), phdr->p_filesz);
|
||||
|
||||
/* clear bss */
|
||||
memset(VOID(phdr->p_vaddr + phdr->p_filesz), 0,
|
||||
phdr->p_memsz - phdr->p_filesz);
|
||||
|
||||
if (phdr->p_memsz) {
|
||||
flush_cache(VOID(phdr->p_vaddr), phdr->p_memsz);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
load_segments(unsigned long *file_addr)
|
||||
{
|
||||
struct ehdr *ehdr = (struct ehdr *) file_addr;
|
||||
/* Calculate program header address */
|
||||
struct phdr *phdr =
|
||||
(struct phdr *) (((unsigned char *) file_addr) + ehdr->e_phoff);
|
||||
int i;
|
||||
/* loop e_phnum times */
|
||||
for (i = 0; i <= ehdr->e_phnum; i++) {
|
||||
/* PT_LOAD ? */
|
||||
if (phdr->p_type == 1) {
|
||||
/* copy segment */
|
||||
load_segment(file_addr, phdr);
|
||||
}
|
||||
/* step to next header */
|
||||
phdr =
|
||||
(struct phdr *) (((unsigned char *) phdr) +
|
||||
ehdr->e_phentsize);
|
||||
}
|
||||
return ehdr->e_entry;
|
||||
}
|
||||
|
||||
static void
|
||||
load_segment64(unsigned long *file_addr, struct phdr64 *phdr64)
|
||||
{
|
||||
unsigned long src = phdr64->p_offset + (unsigned long) file_addr;
|
||||
/* copy into storage */
|
||||
memmove(VOID(phdr64->p_vaddr), VOID(src), phdr64->p_filesz);
|
||||
|
||||
/* clear bss */
|
||||
memset(VOID(phdr64->p_vaddr + phdr64->p_filesz), 0,
|
||||
phdr64->p_memsz - phdr64->p_filesz);
|
||||
|
||||
if (phdr64->p_memsz) {
|
||||
flush_cache(VOID(phdr64->p_vaddr), phdr64->p_memsz);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
load_segments64(unsigned long *file_addr)
|
||||
{
|
||||
struct ehdr64 *ehdr64 = (struct ehdr64 *) file_addr;
|
||||
/* Calculate program header address */
|
||||
struct phdr64 *phdr64 =
|
||||
(struct phdr64 *) (((unsigned char *) file_addr) + ehdr64->e_phoff);
|
||||
int i;
|
||||
/* loop e_phnum times */
|
||||
for (i = 0; i <= ehdr64->e_phnum; i++) {
|
||||
/* PT_LOAD ? */
|
||||
if (phdr64->p_type == 1) {
|
||||
/* copy segment */
|
||||
load_segment64(file_addr, phdr64);
|
||||
}
|
||||
/* step to next header */
|
||||
phdr64 =
|
||||
(struct phdr64 *) (((unsigned char *) phdr64) +
|
||||
ehdr64->e_phentsize);
|
||||
}
|
||||
return ehdr64->e_entry;
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define cpu_to_be32(x) (x)
|
||||
#else
|
||||
#define cpu_to_be32(x) bswap_32(x)
|
||||
#endif
|
||||
#include <byteorder.h>
|
||||
|
||||
/**
|
||||
* elf_check_file tests if the file at file_addr is
|
||||
|
@ -185,7 +38,7 @@ elf_check_file(unsigned long *file_addr)
|
|||
return -1;
|
||||
|
||||
/* endian check */
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (ehdr->ei_data != 2)
|
||||
/* not a big endian image */
|
||||
#else
|
||||
|
@ -194,8 +47,9 @@ elf_check_file(unsigned long *file_addr)
|
|||
#endif
|
||||
return -2;
|
||||
|
||||
/* check if it is an ELF executable */
|
||||
if (ehdr->e_type != 2)
|
||||
/* check if it is an ELF executable ... and also
|
||||
* allow DYN files, since this is specified by ePAPR */
|
||||
if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
|
||||
return -3;
|
||||
|
||||
/* check if it is a PPC ELF executable */
|
||||
|
@ -214,21 +68,98 @@ elf_check_file(unsigned long *file_addr)
|
|||
* @param file_addr pointer to the start of the elf file
|
||||
* @param entry pointer where the ELF loader will store
|
||||
* the entry point
|
||||
* @param pre_load handler that is called before copying a segment
|
||||
* @param post_load handler that is called after copying a segment
|
||||
* @return 1 for a 32 bit file
|
||||
* 2 for a 64 bit file
|
||||
* anything else means an error during load
|
||||
*/
|
||||
int
|
||||
load_elf_file(unsigned long *file_addr, unsigned long *entry)
|
||||
elf_load_file(void *file_addr, unsigned long *entry,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long))
|
||||
{
|
||||
int type = elf_check_file(file_addr);
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
*entry = load_segments(file_addr);
|
||||
*entry = elf_load_segments32(file_addr, 0, pre_load, post_load);
|
||||
break;
|
||||
case 2:
|
||||
*entry = load_segments64(file_addr);
|
||||
*entry = elf_load_segments64(file_addr, 0, pre_load, post_load);
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* load_elf_file_to_addr loads an ELF file to given address.
|
||||
* This is useful for 64-bit vmlinux images that use the virtual entry
|
||||
* point address in their headers, and thereby need a special treatment.
|
||||
*
|
||||
* @param file_addr pointer to the start of the elf file
|
||||
* @param entry pointer where the ELF loader will store
|
||||
* the entry point
|
||||
* @param pre_load handler that is called before copying a segment
|
||||
* @param post_load handler that is called after copying a segment
|
||||
* @return 1 for a 32 bit file
|
||||
* 2 for a 64 bit file
|
||||
* anything else means an error during load
|
||||
*/
|
||||
int
|
||||
elf_load_file_to_addr(void *file_addr, void *addr, unsigned long *entry,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long))
|
||||
{
|
||||
int type;
|
||||
long offset;
|
||||
|
||||
type = elf_check_file(file_addr);
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
/* Parse 32-bit image */
|
||||
offset = (long)addr - elf_get_base_addr32(file_addr);
|
||||
*entry = elf_load_segments32(file_addr, offset, pre_load,
|
||||
post_load) + offset;
|
||||
// TODO: elf_relocate32(...)
|
||||
break;
|
||||
case 2:
|
||||
/* Parse 64-bit image */
|
||||
offset = (long)addr - elf_get_base_addr64(file_addr);
|
||||
*entry = elf_load_segments64(file_addr, offset, pre_load,
|
||||
post_load) + offset;
|
||||
elf_relocate64(file_addr, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the base load address of the ELF image
|
||||
* @return The base address or -1 for error
|
||||
*/
|
||||
long
|
||||
elf_get_base_addr(void *file_addr)
|
||||
{
|
||||
int type;
|
||||
|
||||
type = elf_check_file(file_addr);
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
/* Return 32-bit image base address */
|
||||
return elf_get_base_addr32(file_addr);
|
||||
break;
|
||||
case 2:
|
||||
/* Return 64-bit image base address */
|
||||
return elf_get_base_addr64(file_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/******************************************************************************
|
||||
* 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
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* 32-bit ELF loader
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <libelf.h>
|
||||
|
||||
struct ehdr32 {
|
||||
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;
|
||||
uint32_t e_entry;
|
||||
uint32_t e_phoff;
|
||||
uint32_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 phdr32 {
|
||||
uint32_t p_type;
|
||||
uint32_t p_offset;
|
||||
uint32_t p_vaddr;
|
||||
uint32_t p_paddr;
|
||||
uint32_t p_filesz;
|
||||
uint32_t p_memsz;
|
||||
uint32_t p_flags;
|
||||
uint32_t p_align;
|
||||
};
|
||||
|
||||
|
||||
static struct phdr32*
|
||||
get_phdr32(void *file_addr)
|
||||
{
|
||||
return (struct phdr32 *) (((unsigned char *)file_addr)
|
||||
+ ((struct ehdr32 *)file_addr)->e_phoff);
|
||||
}
|
||||
|
||||
static void
|
||||
load_segment(void *file_addr, struct phdr32 *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 = (unsigned long)phdr->p_paddr;
|
||||
destaddr = destaddr + 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) {
|
||||
post_load((void*)destaddr, phdr->p_memsz);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
elf_load_segments32(void *file_addr, signed long offset,
|
||||
int (*pre_load)(void*, long),
|
||||
void (*post_load)(void*, long))
|
||||
{
|
||||
struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
|
||||
/* Calculate program header address */
|
||||
struct phdr32 *phdr = get_phdr32(file_addr);
|
||||
int i;
|
||||
signed int virt2phys = 0; /* Offset between virtual and physical */
|
||||
|
||||
/* loop e_phnum times */
|
||||
for (i = 0; i <= ehdr->e_phnum; i++) {
|
||||
/* PT_LOAD ? */
|
||||
if (phdr->p_type == 1) {
|
||||
if (!virt2phys) {
|
||||
virt2phys = phdr->p_paddr - phdr->p_vaddr;
|
||||
}
|
||||
/* copy segment */
|
||||
load_segment(file_addr, phdr, offset, pre_load,
|
||||
post_load);
|
||||
}
|
||||
/* step to next header */
|
||||
phdr = (struct phdr32 *)(((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 + virt2phys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_addr32(void *file_addr)
|
||||
{
|
||||
struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
|
||||
struct phdr32 *phdr = get_phdr32(file_addr);
|
||||
int i;
|
||||
|
||||
/* loop e_phnum times */
|
||||
for (i = 0; i <= ehdr->e_phnum; i++) {
|
||||
/* PT_LOAD ? */
|
||||
if (phdr->p_type == 1) {
|
||||
return phdr->p_paddr;
|
||||
}
|
||||
/* step to next header */
|
||||
phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,422 @@
|
|||
/******************************************************************************
|
||||
* 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>
|
||||
|
||||
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;
|
||||
signed long virt2phys = 0; /* Offset between virtual and physical */
|
||||
|
||||
/* loop e_phnum times */
|
||||
for (i = 0; i <= ehdr->e_phnum; i++) {
|
||||
/* PT_LOAD ? */
|
||||
if (phdr->p_type == PT_LOAD) {
|
||||
if (!virt2phys) {
|
||||
virt2phys = phdr->p_paddr - phdr->p_vaddr;
|
||||
}
|
||||
/* 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 + virt2phys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2004, 2008 IBM Corporation
|
||||
* 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
|
||||
|
@ -9,13 +9,35 @@
|
|||
* Contributors:
|
||||
* IBM Corporation - initial implementation
|
||||
*****************************************************************************/
|
||||
int load_elf_file(unsigned long *file_addr, unsigned long *entry);
|
||||
|
||||
PRIM(LOADELF)
|
||||
/*
|
||||
* libelf Forth wrapper
|
||||
*/
|
||||
|
||||
#include <libelf.h>
|
||||
|
||||
// : elf-load-file ( fileaddr -- entry type )
|
||||
PRIM(ELF_X2d_LOAD_X2d_FILE)
|
||||
{
|
||||
void *file_addr = TOS.a;
|
||||
int type;
|
||||
unsigned long entry;
|
||||
type = load_elf_file(file_addr, &entry);
|
||||
type = elf_load_file(file_addr, &entry, elf_forth_claim, flush_cache);
|
||||
TOS.u = entry;
|
||||
PUSH; TOS.n = type;
|
||||
}
|
||||
MIRP
|
||||
|
||||
// : elf-load-file-to-addr ( fileaddr destaddr -- entry type )
|
||||
PRIM(ELF_X2d_LOAD_X2d_FILE_X2d_TO_X2d_ADDR)
|
||||
{
|
||||
void *dest_addr = TOS.a; POP;
|
||||
void *file_addr = TOS.a;
|
||||
int type;
|
||||
unsigned long entry;
|
||||
type = elf_load_file_to_addr(file_addr, dest_addr, &entry,
|
||||
elf_forth_claim, flush_cache);
|
||||
TOS.u = entry;
|
||||
PUSH; TOS.n = type;
|
||||
}
|
||||
MIRP
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2004, 2008 IBM Corporation
|
||||
* 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
|
||||
|
@ -9,4 +9,10 @@
|
|||
* Contributors:
|
||||
* IBM Corporation - initial implementation
|
||||
*****************************************************************************/
|
||||
cod(LOADELF)
|
||||
|
||||
/*
|
||||
* libelf bindings for Forth - definitions
|
||||
*/
|
||||
|
||||
cod(ELF-LOAD-FILE)
|
||||
cod(ELF-LOAD-FILE-TO-ADDR)
|
||||
|
|
|
@ -32,7 +32,7 @@ CFLAGS = -DTARG=$(TARG) -static -Wall -W -std=gnu99 \
|
|||
-fno-stack-protector
|
||||
ASFLAGS = -Wa,-mpower4 -Wa,-mregnames $(FLAG) $(CPUARCHDEF)
|
||||
|
||||
LDFLAGS += -static -nostdlib
|
||||
LDFLAGS += -static -nostdlib -Wl,-q,-n
|
||||
|
||||
ifneq ($(TARG),unix)
|
||||
CFLAGS += -nostdinc -fno-builtin
|
||||
|
@ -91,7 +91,7 @@ paflof: $(SLOFCMNDIR)/OF.lds $(SLOFCMNDIR)/ofw.o paflof.o $(SLOFCMNDIR)/entry.o
|
|||
$(LLFWBRDDIR)/io_generic_lib.o $(LDFLAGS) $(SLOF_LIBS) -o $@
|
||||
#save a copy of paflof before stripping
|
||||
@cp $@ $@.unstripped
|
||||
$(STRIP) -s $@
|
||||
$(STRIP) --strip-unneeded $@
|
||||
|
||||
paflof.o: board.code dict.xt
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(SLOFCMNDIR)/paflof.c
|
||||
|
|
Loading…
Reference in New Issue