From f5a8d498ead94fbaafa2ab2d5da379460b4f18f8 Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Mon, 24 Jul 2017 10:19:49 -0700 Subject: [PATCH] scripts: Convert gen_offset_header to Python By having this as a Python script rather than a host executable, this should simplify the build process on non-Unix platforms. With this change, pyelftools is now required to build Zephyr. Please consult the getting started documentation for your host platform for installation instructions. Jira: ZEP-2062 Signed-off-by: Leandro Pereira --- .gitignore | 1 - Kbuild | 18 +- Makefile | 8 +- doc/getting_started/installation_win.rst | 1 - scripts/gen_offset_header.py | 63 ++ scripts/gen_offset_header/Makefile | 6 - scripts/gen_offset_header/elf.h | 364 ---------- scripts/gen_offset_header/gen_offset_header.c | 670 ------------------ 8 files changed, 74 insertions(+), 1057 deletions(-) create mode 100755 scripts/gen_offset_header.py delete mode 100644 scripts/gen_offset_header/Makefile delete mode 100644 scripts/gen_offset_header/elf.h delete mode 100644 scripts/gen_offset_header/gen_offset_header.c diff --git a/.gitignore b/.gitignore index 0d507b37200..afbc711b2cf 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ outdir outdir-* scripts/basic/fixdep scripts/gen_idt/gen_idt -scripts/gen_offset_header/gen_offset_header scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/zconf.hash.c diff --git a/Kbuild b/Kbuild index ceaa9378fc7..7f436878e7b 100644 --- a/Kbuild +++ b/Kbuild @@ -51,15 +51,15 @@ arch/$(ARCH)/core/offsets/offsets.o: arch/$(ARCH)/core/offsets/offsets.c $(KCONF define offsetchk - $(Q)set -e; \ - $(kecho) ' CHK $@'; \ - mkdir -p $(dir $@); \ - $(GENOFFSET_H) -i $(1) -o $@.tmp; \ - if [ -r $@ ] && cmp -s $@ $@.tmp; then \ - rm -f $@.tmp; \ - else \ - $(kecho) ' UPD $@'; \ - mv -f $@.tmp $@; \ + $(Q)set -e; \ + $(kecho) ' CHK $@'; \ + mkdir -p $(dir $@); \ + $(srctree)/scripts/gen_offset_header.py -i $(1) -o $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + $(kecho) ' UPD $@'; \ + mv -f $@.tmp $@; \ fi endef diff --git a/Makefile b/Makefile index 18b793235a6..6dac4581474 100644 --- a/Makefile +++ b/Makefile @@ -320,10 +320,8 @@ GDB = $(CROSS_COMPILE)gdb READELF = $(CROSS_COMPILE)readelf AWK = awk ifeq ($(PREBUILT_HOST_TOOLS),) -GENOFFSET_H = scripts/gen_offset_header/gen_offset_header FIXDEP = scripts/basic/fixdep else -GENOFFSET_H = $(PREBUILT_HOST_TOOLS)/gen_offset_header ifneq ($(filter host-tools, $(MAKECMDGOALS)),) FIXDEP = scripts/basic/fixdep else @@ -416,7 +414,7 @@ exports += VERSION_MAJOR VERSION_MINOR PATCHLEVEL VERSION_RESERVED EXTRAVERSION exports += KERNELRELEASE KERNELVERSION exports += ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC CXX exports += CPP AR NM STRIP OBJCOPY OBJDUMP GDB -exports += MAKE AWK INSTALLKERNEL PERL PYTHON GENOFFSET_H +exports += MAKE AWK INSTALLKERNEL PERL PYTHON exports += HOSTCXX HOSTCXXFLAGS CHECK CHECKFLAGS exports += KBUILD_CPPFLAGS NOSTDINC_FLAGS ZEPHYRINCLUDE OBJCOPYFLAGS LDFLAGS @@ -456,7 +454,6 @@ PHONY += scripts_basic ifeq ($(PREBUILT_HOST_TOOLS),) scripts_basic: $(Q)$(MAKE) $(build)=scripts/basic - $(Q)$(MAKE) $(build)=scripts/gen_offset_header else scripts_basic: endif @@ -1278,10 +1275,9 @@ host-tools: $(Q)$(MAKE) $(build)=scripts/basic $(Q)$(MAKE) $(build)=scripts/kconfig standalone $(Q)$(MAKE) $(build)=scripts/gen_idt - $(Q)$(MAKE) $(build)=scripts/gen_offset_header @mkdir -p ${ZEPHYR_BASE}/bin @cp scripts/basic/fixdep scripts/gen_idt/gen_idt scripts/kconfig/conf \ - scripts/gen_offset_header/gen_offset_header ${ZEPHYR_BASE}/bin + ${ZEPHYR_BASE}/bin # Documentation targets diff --git a/doc/getting_started/installation_win.rst b/doc/getting_started/installation_win.rst index 422fc053c77..c3abbd77a48 100644 --- a/doc/getting_started/installation_win.rst +++ b/doc/getting_started/installation_win.rst @@ -63,7 +63,6 @@ environment for Windows. Follow the steps below to set it up: $ curl -O 'https://bootstrap.pypa.io/get-pip.py' $ ./get-pip.py $ rm get-pip.py - $ pip install -r scripts/requirements.txt #. Build the Device Tree Compiler (DTC) diff --git a/scripts/gen_offset_header.py b/scripts/gen_offset_header.py new file mode 100755 index 00000000000..b66235c0595 --- /dev/null +++ b/scripts/gen_offset_header.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2017 Intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection +import argparse +import sys + +def get_symbol_table(obj): + for section in obj.iter_sections(): + if isinstance(section, SymbolTableSection): + return section + + raise LookupError("Could not find symbol table") + +def gen_offset_header(input_name, input_file, output_file): + include_guard = "__INCLUDE_GUARD_%016x__" % abs(input_name.__hash__()) + output_file.write("""/* THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT. + * + * This header file provides macros for the offsets of various structure + * members. These offset macros are primarily intended to be used in + * assembly code. + */ + +#ifndef %s +#define %s\n\n""" % (include_guard, include_guard)) + + obj = ELFFile(input_file) + for sym in get_symbol_table(obj).iter_symbols(): + if isinstance(sym.name, bytes): + sym.name = str(sym.name, 'ascii') + + if not sym.name.endswith(('_OFFSET', '_SIZEOF')): + continue + if sym.entry['st_shndx'] != 'SHN_ABS': + continue + if sym.entry['st_info']['bind'] != 'STB_GLOBAL': + continue + + output_file.write("#define %s 0x%x\n" % (sym.name, sym.entry['st_value'])) + + output_file.write("\n#endif /* %s */\n" % include_guard) + + return 0 + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + formatter_class = argparse.RawDescriptionHelpFormatter) + + parser.add_argument("-i", "--input", required=True, help="Input object file") + parser.add_argument("-o", "--output", required=True, help="Output header file") + + args = parser.parse_args() + + input_file = open(args.input, 'rb') + output_file = open(args.output, 'w') + + ret = gen_offset_header(args.input, input_file, output_file) + sys.exit(ret) diff --git a/scripts/gen_offset_header/Makefile b/scripts/gen_offset_header/Makefile deleted file mode 100644 index 8e6f3b37630..00000000000 --- a/scripts/gen_offset_header/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -HOSTCFLAGS_gen_offset_header.o += -DKERNEL_VERSION=0 -Wall -Werror -g -HOSTCFLAGS_gen_idt.o += -Wno-unused-result - -hostprogs-y += gen_offset_header -gen_offset_header-objs := gen_offset_header.o -always := $(hostprogs-y) diff --git a/scripts/gen_offset_header/elf.h b/scripts/gen_offset_header/elf.h deleted file mode 100644 index cf85d7ce191..00000000000 --- a/scripts/gen_offset_header/elf.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2010, 2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* @file - * @brief Executable and Linking Format (ELF) definitions - * - * The definitions in this header conform to the "Tool Interface Standard (TIS) - * Executable and Linking Format (ELF) Specification Version 1.2" - */ - -#ifndef _ELF_H -#define _ELF_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned int Elf32_Addr; -typedef unsigned short Elf32_Half; -typedef unsigned int Elf32_Off; -typedef int Elf32_Sword; -typedef unsigned int Elf32_Word; - - -/* - * Elf header - */ - -#define EI_NIDENT 16 - -typedef struct - { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; - } Elf32_Ehdr; - -#define EHDRSZ sizeof(Elf32_Ehdr) - -/* - * e_ident[] values - */ -#define EI_MAG0 0 -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_PAD 7 - -#define ELFMAG0 0x7f -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -/* - * EI_CLASS - */ -#define ELFCLASSNONE 0 -#define ELFCLASS32 1 -#define ELFCLASS64 2 - -/* - * EI_DATA - */ -#define ELFDATANONE 0 -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -/* - * e_type - */ -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - -/* - * e_machine - */ -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola 68000 */ -#define EM_88K 5 /* Motorola 88000 */ -#define EM_486 6 /* Intel 80486 */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ -#define EM_MIPS_RS4_BE 10 /* MIPS RS4000 Big-Endian */ -#define EM_PPC_OLD 17 /* PowerPC - old */ -#define EM_PPC 20 /* PowerPC */ -#define EM_RCE_OLD 25 /* RCE - old */ -#define EM_NEC_830 36 /* NEC 830 series */ -#define EM_RCE 39 /* RCE */ -#define EM_MCORE 39 /* MCORE */ -#define EM_ARM 40 /* ARM */ -#define EM_SH 42 /* SH */ -#define EM_COLDFIRE 52 /* Motorola ColdFire */ -#define EM_SC 58 /* SC */ -#define EM_M32R 36929 /* M32R */ -#define EM_NEC 36992 /* NEC 850 series */ - -/* - * e_flags - */ -#define EF_PPC_EMB 0x80000000 - -#define EF_MIPS_NOREORDER 0x00000001 -#define EF_MIPS_PIC 0x00000002 -#define EF_MIPS_CPIC 0x00000004 -#define EF_MIPS_ARCH 0xf0000000 -#define EF_MIPS_ARCH_MIPS_2 0x10000000 -#define EF_MIPS_ARCH_MIPS_3 0x20000000 - -/* - * e_version and EI_VERSION - */ -#define EV_NONE 0 -#define EV_CURRENT 1 - -/* - * Special section indexes - */ -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -#define SHN_GHCOMMON 0xff00 -/* - * Section header - */ -typedef struct - { - Elf32_Word sh_name; - Elf32_Word sh_type; /* SHT_... */ - Elf32_Word sh_flags; /* SHF_... */ - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -#define SHDRSZ sizeof(Elf32_Shdr) - -/* - * sh_type - */ -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_COMDAT 12 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff -#define SHT_INIT_ARRAY 14 -#define SHT_FINI_ARRAY 15 -#define SHT_PREINIT_ARRAY 16 -#define SHT_GROUP 17 -#define SHT_SYMTAB_SHNDX 18 -#define SHT_NUM 19 - -/* - * sh_flags - */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 -#define SHF_MERGE 0x10 /* not part of all ELF ABI docs */ -#define SHF_STRINGS 0x20 /* not part of all ELF ABI docs */ -#define SHF_INFO_LINK 0x40 -#define SHF_LINK_ORDER 0x80 -#define SHF_OS_NONCONFORMING 0x100 -#define SHF_GROUP 0x200 -#define SHF_TLS 0x400 - -/* - * Symbol table - */ -typedef struct - { - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; - } Elf32_Sym; - -#define STN_UNDEF 0 - -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_LOPROC 13 -#define STB_HIPROC 15 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 -#define STT_LOOS 10 -#define STT_HIOS 12 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - -#define ELF_ST_BIND(x) ((x) >> 4) -#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) -#define ELF32_ST_BIND(x) ELF_ST_BIND(x) -#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) - - -/* - * The STT_ARM_TFUNC type is used by the gnu compiler to mark Thumb - * functions. The STT_ARM_16BIT type is the thumb equivalent of an - * object. They are not part of the ARM ABI or EABI - they come from gnu. - */ - -#define STT_ARM_TFUNC STT_LOPROC /* GNU Thumb function */ -#define STT_ARM_16BIT STT_HIPROC /* GNU Thumb label */ - - -/* - * Relocation - */ -typedef struct - { - Elf32_Addr r_offset; - Elf32_Word r_info; - } Elf32_Rel; - -typedef struct - { - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; - } Elf32_Rela; - -#define ELF32_R_SYM(info) ((info)>>8) -#define ELF32_R_TYPE(info) ((unsigned char)(info)) -#define ELF32_R_INFO(sym,type) (((sym)<<8)+(unsigned char)(type)) - -/* - * Program header - */ -typedef struct - { - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; - } Elf32_Phdr; - -#define PHDRSZ sizeof(Elf32_Phdr) - -/* - * p_type - */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -/* - * p_flags - */ -#define PF_X 0x1 -#define PF_W 0x2 -#define PF_R 0x4 -#define PF_MASKPROC 0xf0000000 - -typedef struct - { - Elf32_Sword d_tag; - union - { - Elf32_Word d_val; - Elf32_Addr d_ptr; - } d_un; - } Elf32_Dyn; - -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - - -#ifdef __cplusplus -} -#endif - -#endif /* _ELF_H */ diff --git a/scripts/gen_offset_header/gen_offset_header.c b/scripts/gen_offset_header/gen_offset_header.c deleted file mode 100644 index 5933970be1f..00000000000 --- a/scripts/gen_offset_header/gen_offset_header.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - * Copyright (c) 2010-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief generate offset definition header file - * - * genOffsetHeader -i -o - * - * This Zephyr development host utility will process an ELF object module that - * consists of a series of absolute symbols representing the byte offset of a - * structure member and the size of the structure. Each absolute symbol will - * be translated into a C preprocessor '#define' directive. For example, - * assuming that the module offsets.o contains the following absolute symbols: - * - * $ nm offsets.o - * 00000000 A ___kernel_t_nested_OFFSET - * 00000004 A ___kernel_t_irq_stack_OFFSET - * 00000008 A ___kernel_t_current_OFFSET - * 0000000c A ___kernel_t_idle_OFFSET - * - * ... the following C preprocessor code will be generated: - * - * #define ___kernel_t_nested_OFFSET 0x0 - * #define ___kernel_t_irq_stack_OFFSET 0x4 - * #define ___kernel_t_current_OFFSET 0x8 - * #define ___kernel_t_idle_OFFSET 0xc - */ - -/* includes */ - -#include -#include -#include -#include -#include -#include "elf.h" -#include /* for malloc()/free()/exit() */ -#include /* for strstr() */ -#include -#include - -/* defines */ - -#undef DEBUG - -/* the symbol name suffix used to denote structure member offsets */ - -#define STRUCT_OFF_SUFFIX "_OFFSET" -#define STRUCT_SIZ_SUFFIX "_SIZEOF" - -#ifdef DEBUG -#define DBG_PRINT(args...) printf(args) -#else -#define DBG_PRINT(args...) -#endif - - -/* byte swapping macros */ - -#define SWAB_Elf32_Half(x) ((x >> 8) | (x << 8)) -#define SWAB_Elf32_Word(x) (((x >> 24) & 0xff) | \ - ((x << 8) & 0xff0000) | \ - ((x >> 8) & 0xff00) | \ - ((x << 24) & 0xff000000)) - -#define SWAB_Elf32_Addr SWAB_Elf32_Word -#define SWAB_Elf32_Off SWAB_Elf32_Word -#define SWAB_Elf32_Sword SWAB_Elf32_Word - -#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__WIN32__) - #define OPEN_FLAGS (O_RDONLY|O_BINARY) -#else - #define OPEN_FLAGS (O_RDONLY) -#endif - -/* locals */ - -/* global indicating whether ELF structures need to be byte swapped */ - -static char swabRequired; - - -/* usage information */ - -static char usage[] = "usage: %s -i -o \n"; - - -/* output header file preamble */ - -static char preamble1[] = "\ -/* %s - structure member offsets definition header */\n\ -\n\ -/*\n\ - * Copyright (c) 2010-2014 Wind River Systems, Inc.\n\ - *\n\ - * Licensed under the Apache License, Version 2.0 (the \"License\");\n\ - * you may not use this file except in compliance with the License.\n\ - * You may obtain a copy of the License at\n\ - *\n\ - * http://www.apache.org/licenses/LICENSE-2.0\n\ - *\n\ - * Unless required by applicable law or agreed to in writing, software\n\ - * distributed under the License is distributed on an \"AS IS\" BASIS,\n\ - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\ - * See the License for the specific language governing permissions and\n\ - * limitations under the License.\n\ - * SPDX-License-Identifier: Apache-2.0\n\ - */\n\ -\n\ -/* THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT */\n\ -\n\ -/*\n\ - * This header file provides macros for the offsets of various structure\n\ - * members. These offset macros are primarily intended to be used in\n\ - * assembly code.\n\ - */\n\n"; - -static char preamble2[] = "\ -/*\n\ - * Auto-generated header guard.\n\ - */\n\ -#ifndef %s\n\ -#define %s\n\ - \n\ -#ifdef __cplusplus\n\ -extern \"C\" {\n\ -#endif\n\ -\n\ -/* defines */\n\n"; - - -/* output header file postscript */ - -static char postscript[] = "\ -\n\ -#ifdef __cplusplus\n\ -}\n\ -#endif\n\ -\n\ -#endif /* _HGUARD_ */\n"; - -static Elf32_Ehdr ehdr; /* ELF header */ -static Elf32_Shdr * shdr; /* pointer to array ELF section headers */ - -/** - * @brief byte swap the Elf32_Ehdr structure - * - * @returns N/A - */ -static void swabElfHdr(Elf32_Ehdr *pHdrToSwab) -{ - if (swabRequired == 0) - { - return; /* do nothing */ - } - - pHdrToSwab->e_type = SWAB_Elf32_Half(pHdrToSwab->e_type); - pHdrToSwab->e_machine = SWAB_Elf32_Half(pHdrToSwab->e_machine); - pHdrToSwab->e_version = SWAB_Elf32_Word(pHdrToSwab->e_version); - pHdrToSwab->e_entry = SWAB_Elf32_Addr(pHdrToSwab->e_entry); - pHdrToSwab->e_phoff = SWAB_Elf32_Off(pHdrToSwab->e_phoff); - pHdrToSwab->e_shoff = SWAB_Elf32_Off(pHdrToSwab->e_shoff); - pHdrToSwab->e_flags = SWAB_Elf32_Word(pHdrToSwab->e_flags); - pHdrToSwab->e_ehsize = SWAB_Elf32_Half(pHdrToSwab->e_ehsize); - pHdrToSwab->e_phentsize = SWAB_Elf32_Half(pHdrToSwab->e_phentsize); - pHdrToSwab->e_phnum = SWAB_Elf32_Half(pHdrToSwab->e_phnum); - pHdrToSwab->e_shentsize = SWAB_Elf32_Half(pHdrToSwab->e_shentsize); - pHdrToSwab->e_shnum = SWAB_Elf32_Half(pHdrToSwab->e_shnum); - pHdrToSwab->e_shstrndx = SWAB_Elf32_Half(pHdrToSwab->e_shstrndx); -} - -/** - * @brief byte swap the Elf32_Shdr structure - * - * @returns N/A - */ -static void swabElfSectionHdr(Elf32_Shdr *pHdrToSwab) -{ - if (swabRequired == 0) - { - return; /* do nothing */ - } - - pHdrToSwab->sh_name = SWAB_Elf32_Word(pHdrToSwab->sh_name); - pHdrToSwab->sh_type = SWAB_Elf32_Word(pHdrToSwab->sh_type); - pHdrToSwab->sh_flags = SWAB_Elf32_Word(pHdrToSwab->sh_flags); - pHdrToSwab->sh_addr = SWAB_Elf32_Addr(pHdrToSwab->sh_addr); - pHdrToSwab->sh_offset = SWAB_Elf32_Off(pHdrToSwab->sh_offset); - pHdrToSwab->sh_size = SWAB_Elf32_Word(pHdrToSwab->sh_size); - pHdrToSwab->sh_link = SWAB_Elf32_Word(pHdrToSwab->sh_link); - pHdrToSwab->sh_info = SWAB_Elf32_Word(pHdrToSwab->sh_info); - pHdrToSwab->sh_addralign = SWAB_Elf32_Word(pHdrToSwab->sh_addralign); - pHdrToSwab->sh_addralign = SWAB_Elf32_Word(pHdrToSwab->sh_addralign); -} - - -/** - * - * @brief byte swap the Elf32_Sym structure - * - * @returns N/A - */ -static void swabElfSym(Elf32_Sym *pHdrToSwab) -{ - if (swabRequired == 0) - { - return; /* do nothing */ - } - - pHdrToSwab->st_name = SWAB_Elf32_Word(pHdrToSwab->st_name); - pHdrToSwab->st_value = SWAB_Elf32_Addr(pHdrToSwab->st_value); - pHdrToSwab->st_size = SWAB_Elf32_Word(pHdrToSwab->st_size); - pHdrToSwab->st_shndx = SWAB_Elf32_Half(pHdrToSwab->st_shndx); -} - -/** - * @brief load the ELF header - * - * @param fd file descriptor of file from which to read - * @returns 0 on success, -1 on failure - */ -static int ehdrLoad(int fd) -{ - unsigned ix = 0x12345678; /* used to auto-detect endian-ness */ - size_t nBytes; /* number of bytes read from file */ - - if (lseek(fd, 0, SEEK_SET) == -1) { - fprintf(stderr, "Unable to seek\n"); - return -1; - } - - nBytes = read(fd, &ehdr, sizeof(ehdr)); - if (nBytes != sizeof(ehdr)) - { - fprintf(stderr, "Failed to read ELF header\n"); - return -1; - } - - /* perform some rudimentary ELF file validation */ - - if (strncmp((char *)ehdr.e_ident, ELFMAG, 4) != 0) - { - fprintf(stderr, "Input object module not ELF format\n"); - return -1; - } - - /* 64-bit ELF module not supported (for now) */ - - if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) - { - fprintf(stderr, "ELF64 class not supported\n"); - return -1; - } - - /* - * Dynamically determine the endianess of the host (in the absence of - * a compile time macro ala _BYTE_ORDER). The ELF structures will require - * byte swapping if the host and target have different byte ordering. - */ - - if (((*(char*)&ix == 0x78) && (ehdr.e_ident[EI_DATA] == ELFDATA2MSB)) || - ((*(char*)&ix == 0x12) && (ehdr.e_ident[EI_DATA] == ELFDATA2LSB))) - { - swabRequired = 1; - DBG_PRINT("Swab required\n"); - } - - swabElfHdr(&ehdr); /* swap bytes (if required) */ - - /* debugging: dump some important ELF header fields */ - - DBG_PRINT("Elf header Magic = %s\n", ehdr.e_ident); - DBG_PRINT("Elf header e_type = %d\n", ehdr.e_type); - DBG_PRINT("Elf header e_shstrndx = %d\n", ehdr.e_shstrndx); - DBG_PRINT("Elf header e_shnum = %d\n", ehdr.e_shnum); - - return 0; -} - -/** - * @brief load the section headers - * @param fd file descriptor of file from which to read - * - * @returns 0 on success, -1 on failure - */ -static int shdrsLoad(int fd) -{ - size_t nBytes; /* number of bytes read from file */ - unsigned ix; /* loop index */ - - shdr = malloc(ehdr.e_shnum * sizeof(Elf32_Shdr)); - if (shdr == NULL) - { - fprintf(stderr, "No memory for section headers!\n"); - return -1; - } - - /* Seek to the start of the table of section headers */ - if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1) { - fprintf(stderr, "Unable to seek\n"); - return -1; - } - - for (ix = 0; ix < ehdr.e_shnum; ix++) - { - nBytes = read(fd, &shdr[ix], sizeof(Elf32_Shdr)); - if (nBytes != sizeof(Elf32_Shdr)) - { - fprintf(stderr, "Unable to read entire section header (#%d)\n", - ix); - return -1; - } - - swabElfSectionHdr(&shdr[ix]); /* swap bytes (if required) */ - } - - return 0; -} - -/** - * - * symTblFind - search the section headers for the symbol table - * - * This routine searches the section headers for the symbol table. There is - * expected to be only one symbol table in the section headers. - * - * @param pSymTblOffset ptr to symbol table offset - * @param pSymTblSize ptr to symbol table size - * @returns 0 if found, -1 if not - */ -static int symTblFind(unsigned *pSymTblOffset, unsigned *pSymTblSize) -{ - unsigned ix; /* loop index */ - - for (ix = 0; ix < ehdr.e_shnum; ++ix) - { - if (shdr[ix].sh_type == SHT_SYMTAB) - { - *pSymTblOffset = shdr[ix].sh_offset; - *pSymTblSize = shdr[ix].sh_size; - - return 0; - } - } - - fprintf(stderr, "Object module missing symbol table!\n"); - - return -1; -} - -/** - * - * @brief search the section headers for the string table - * - * This routine searches the section headers for the string table associated - * with the symbol names. - * - * Typically, there are two string tables defined in the section headers. These - * are ".shstrtbl" and ".strtbl" for section header names and symbol names - * respectively. It has been observed with the DIAB compiler (but not with - * either the GCC nor ICC compilers) that the two tables may be mashed together - * into one. Consequently, the following algorithm is used to select the - * appropriate string table. - * - * 1. Assume that the first found string table is valid. - * 2. If another string table is found, use that only if its section header - * index does not match the index for ".shstrtbl" stored in the ELF header. - * - * @param pStrTblIx ptr to string table's index - * @returns 0 if found, -1 if not - */ -static int strTblFind(unsigned *pStrTblIx) -{ - unsigned strTblIx = 0xffffffff; - unsigned ix; - - for (ix = 0; ix < ehdr.e_shnum; ++ix) - { - if (shdr[ix].sh_type == SHT_STRTAB) - { - if ((strTblIx == 0xffffffff) || - (ix != ehdr.e_shstrndx)) - { - strTblIx = ix; - } - } - } - - if (strTblIx == 0xffffffff) - { - fprintf(stderr, "Object module missing string table!\n"); - return -1; - } - - *pStrTblIx = strTblIx; - - return 0; -} - -/** - * @brief load the string table - * - * @param fd file descriptor of file from which to read - * @param strTblIx string table's index - * @param ppStringTable ptr to ptr to string table - * @returns 0 on success, -1 on failure - */ -static int strTblLoad(int fd, unsigned strTblIx, char **ppStringTable) -{ - char * pTable; - int nBytes; - - DBG_PRINT("Allocating %d bytes for string table\n", - shdr[strTblIx].sh_size); - - pTable = malloc(shdr[strTblIx].sh_size); - if (pTable == NULL) - { - fprintf(stderr, "No memory for string table!"); - return -1; - } - - if (lseek(fd, shdr[strTblIx].sh_offset, SEEK_SET) == -1) { - free(pTable); - fprintf(stderr, "Unable to seek\n"); - return -1; - } - - nBytes = read(fd, pTable, shdr[strTblIx].sh_size); - if (nBytes != shdr[strTblIx].sh_size) - { - free(pTable); - fprintf(stderr, "Unable to read entire string table!\n"); - return -1; - } - - *ppStringTable = pTable; - - return 0; -} - -/** - * - * @brief dump the header preamble to the header file - * - * @param fd file pointer to which to write - * @parama filename name of the output file - * @returns N/A - */ -static void headerPreambleDump(FILE *fp, char *filename) -{ - unsigned hash = 5381; /* hash value */ - size_t ix; /* loop counter */ - char fileNameHash[20]; /* '_HGUARD_' + 8 character hash + '\0' */ - - /* dump header file preamble1[] */ - - fprintf(fp, preamble1, filename, filename, filename); - - /* - * Dump header file preamble2[]. Hash file name into something that - * is small enough to be a C macro name and does not have invalid - * characters for a macro name to use as a header guard. The result - * of the hash should be unique enough for our purposes. - */ - - for (ix = 0; ix < sizeof(filename); ++ix) - { - hash = (hash * 33) + (unsigned int) filename[ix]; - } - - sprintf(fileNameHash, "_HGUARD_%08x", hash); - fprintf(fp, preamble2, fileNameHash, fileNameHash); -} - -/** - * @brief dump the absolute symbols to the header file - * - * @param fd file descriptor of file from which to read - * @param fp file pointer to which to write - * @param symTblOffset symbol table offset - * @param symTblSize size of the symbol table - * @param pStringTable ptr to the string table - * @returns N/A - */ -static void headerAbsoluteSymbolsDump(int fd, FILE *fp, Elf32_Off symTblOffset, - Elf32_Word symTblSize, char *pStringTable) -{ - Elf32_Sym aSym; /* absolute symbol */ - unsigned ix; /* loop counter */ - unsigned numSyms; /* number of symbols in the symbol table */ - size_t nBytes; - - /* context the symbol table: pick out absolute syms */ - - numSyms = symTblSize / sizeof(Elf32_Sym); - if (lseek(fd, symTblOffset, SEEK_SET) == -1) { - fprintf(stderr, "Unable to seek\n"); - return; - } - - for (ix = 0; ix < numSyms; ++ix) - { - /* read in a single symbol structure */ - nBytes = read(fd, &aSym, sizeof(Elf32_Sym)); - - if (nBytes) { - swabElfSym(&aSym); /* swap bytes (if required) */ - } - - /* - * Only generate definitions for global absolute symbols - * of the form *_OFFSET - */ - - if ((aSym.st_shndx == SHN_ABS) && - (ELF_ST_BIND(aSym.st_info) == STB_GLOBAL)) - { - if ((strstr(&pStringTable[aSym.st_name], - STRUCT_OFF_SUFFIX) != NULL) || - (strstr(&pStringTable[aSym.st_name], - STRUCT_SIZ_SUFFIX) != NULL)) - { - fprintf(fp, "#define\t%s\t0x%X\n", - &pStringTable[aSym.st_name], aSym.st_value); - } - } - } -} - -/** - * - * @brief dump the header postscript to the header file - * @param fp file pointer to which to write - * @returns N/A - */ -static void headerPostscriptDump(FILE *fp) -{ - fputs(postscript, fp); -} - -/** - * @brief entry point for the genOffsetHeader utility - * - * usage: $ genOffsetHeader -i -o - * - * @returns 0 on success, 1 on failure - */ -int main(int argc, char *argv[]) -{ - Elf32_Off symTblOffset = 0; - Elf32_Word symTblSize; /* in bytes */ - char * pStringTable = NULL; - char * inFileName = NULL; - char * outFileName = NULL; - int option; - int inFd = -1; - FILE * outFile = NULL; - unsigned strTblIx; - - /* argument parsing */ - - if (argc != 5) - { - fprintf(stderr, usage, argv[0]); - goto errorReturn; - } - - while ((option = getopt(argc, argv, "i:o:")) != -1) - { - switch (option) - { - case 'i': - inFileName = optarg; - break; - case 'o': - outFileName = optarg; - break; - default: - fprintf(stderr, usage, argv[0]); - goto errorReturn; - } - } - - /* open input object ELF module and output header file */ - - inFd = open(inFileName, OPEN_FLAGS); - - if (inFd == -1) - { - fprintf(stderr, "Cannot open input object module"); - goto errorReturn; - } - - outFile = fopen(outFileName, "w"); - - if (outFile == NULL) - { - fprintf(stderr, "Cannot open output header file"); - goto errorReturn; - } - - /* - * In the following order, attempt to ... - * 1. Load the ELF header - * 2. Load the section headers - * 3. Find the symbol table - * 4. Find the string table - * 5. Load the string table - * Bail if any of those steps fail. - */ - - if ((ehdrLoad(inFd) != 0) || - (shdrsLoad(inFd) != 0) || - (symTblFind(&symTblOffset, &symTblSize) != 0) || - (strTblFind(&strTblIx) != 0) || - (strTblLoad(inFd, strTblIx, &pStringTable) != 0)) - { - goto errorReturn; - } - - - /* - * Dump the following to the header file ... - * 1. Header file preamble - * 2. Absolute symbols - * 3. Header file postscript - */ - - headerPreambleDump(outFile, outFileName); - headerAbsoluteSymbolsDump(inFd, outFile, - symTblOffset, symTblSize, pStringTable); - headerPostscriptDump(outFile); - - /* done: cleanup */ - - close(inFd); - fclose(outFile); - free(shdr); - free(pStringTable); - - return 0; - -errorReturn: - if (inFd != -1) - { - close(inFd); - } - - if (outFile != NULL) - { - fclose(outFile); - } - - if (shdr != NULL) - { - free(shdr); - } - - if (pStringTable != NULL) - { - free(pStringTable); - } - - return 1; -}