Mercurial > ecos
changeset 2011:662e1b34b811
Added OBJLOADER package.
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,7 @@ +2005-06-28 Nick Garnett <nickg@ecoscentric.com> + + * ecos.db: Added Object Loader package. + 2005-06-12 Brandl Harald <Harald.Brandl@fh-joanneum.at> * ecos.db: Added a ethernet device driver for the NETARM.
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -2136,6 +2136,14 @@ This package provides support for the dy library loader." } +package CYGPKG_OBJLOADER { + alias { "Object file loader" objloader } + directory services/objloader + script objloader.cdl + description " +This package provides support for the object file loader and relocator." +} + package CYGPKG_COMPRESS_ZLIB { alias { "Zlib compress/decompress" zlib_compress compress_zlib zlib } directory services/compress/zlib @@ -5956,3 +5964,4 @@ package CYGPKG_NET_LWIP { description "Lightweight TCP/IP stack: lwIP" } +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/ChangeLog @@ -0,0 +1,48 @@ +2005-05-10 Anthony Tonizzo <atonizzo@lycos.com> + + * include/elf.h: + * include/loader_fs.h: + * include/objelf.h: + * include/relocate_ppc.h: + * src/loader_fs.c: + * src/objelf.c: + * src/objloader.c: + * src/relocate_ppc.c: + * doc/notes.txt: + * cdl/objloader.cdl: + * tests/test_mods.c: + * tests/library/hello.c: + Created OBJLDR package. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005 eCosCentric Ltd. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/cdl/objloader.cdl @@ -0,0 +1,165 @@ +# ==================================================================== +# +# objloader.cdl +# +# Object loader configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2005 eCosCentric Ltd. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): atonizzo (atonizzo@lycos.com) +# Contributors: +# Date: 2005-05-13 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_OBJLOADER { + display "Object file loader" + description "This package provides support for loading and relocating + object files within eCos." + include_dir cyg/objloader + include_files elf.h objelf.h loader_fs.h relocate_ppc.h + compile objloader.c objelf.c loader_fs.c + requires CYGPKG_MEMALLOC + requires CYGPKG_IO_FILEIO +# ==================================================================== + + cdl_component CYGPKG_SERVICES_OBJLOADER_ARCHITECTURE { + display "Architecture dependent settings" + flavor none + no_define + description "Each of the options here enables the correct + relocation support for the architectures supported." + + cdl_option CYGBLD_OBJLOADER_ARCHITECTURE_POWERPC { + display "Support loading on PowerPC processors" + calculated CYGPKG_HAL_POWERPC + define_proc { + puts $::cdl_header "#include <cyg/objloader/relocate_ppc.h>" + } + compile relocate_ppc.c + } + +# cdl_option CYGBLD_OBJLOADER_ARCHITECTURE_ARM { +# display "Support loading on ARM processors" +# calculated CYGPKG_HAL_ARM +# define_proc { +# puts $::cdl_header "#include <cyg/objloader/relocate_arm.h>" +# } +# compile relocate_arm.c +# } + + } + + cdl_option CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL { + display "Verbosity of debug output" + flavor data + legal_values 0 1 2 + default_value 0 + description "This option allows controls over the verbosity of + the debug output. 1 is moderate, 2 is very + verbose, including the symbol name of each relocation + performed. Any value other than 0 will prevent the + unloading of unused library data, thus increasing the + heap memory requirements of the package." + } + + cdl_component CYGPKG_SERVICES_OBJLOADER_OPTIONS { + display "Object loader build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + + cdl_option CYGPKG_SERVICES_OBJLOADER_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the serial device drivers. These flags are + used in addition to the set of global flags." + } + + cdl_option CYGPKG_SERVICES_OBJLOADER_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the serial device drivers. These flags are + removed from the set of global flags if present." + } + } + + cdl_option CYGBLD_SERVICES_OBJLOADER_BUILD_TESTS { + display "Build test library" + default_value 0 + no_define + description " + This option enables the building of a library and an + application for testing the loader. These + are not built by default since they do not use the dedicated + testing infrastructure." + + make -priority 320 { + <PREFIX>/bin/test_mods : <PACKAGE>/tests/test_mods.c + @sh -c "mkdir -p tests $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/test_mods.o $< + @echo $@ ": \\" > $(notdir $@).deps + @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps + @tail -n +2 deps.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm deps.tmp + $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/test_mods.o + } + + make -priority 320 { + <PREFIX>/bin/hello.o : <PACKAGE>/tests/library/hello.c + @sh -c "mkdir -p tests $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -I$(dir $<) $(CFLAGS) -o $@ $< + } + } + + +} + +# ==================================================================== +# EOF objloader.cdl
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/doc/notes.txt @@ -0,0 +1,156 @@ +These are very preliminary notes on the design and use of the object loader. +Users should be aware that the package is still undergoing some changes. +Feedback is appreciated. + +-------------------------------------------------------------------------------- +Creating libraries +-------------------------------------------------------------------------------- +Libraries can be created by simply compiling the sources into .o files. +The typical command line will look something like this: + +<toolchain>-gcc -c -I$(ECOS_DIRECTORY)/include -Wall hello.c + +The eCos "include" directory is needed to get the header files for the API. +Multiple object files can be compiled into a single object with the + +<toolchain>-ld -r -o out.o file1.o file2.o file3.o + +It must be noted that the use of a linker to collect multiple object files +into a single one considerably increases the size of the symbol table. + +-------------------------------------------------------------------------------- +Init/fini functions +-------------------------------------------------------------------------------- +When the library is loaded the loader will look for a symbol with the name of +"library_open" and, if found, will call the symbol with a prototype of + +void library_open( void ) + +When the cyg_ldr_close_library() function is called, the loader will also +look for a function called library close() and call it. The prototype is the +same as library_open(). + +-------------------------------------------------------------------------------- +External references. +-------------------------------------------------------------------------------- +External references are the calls that the library makes to the eCos. These +calls are resolved by the loader if the function name is available in a table +provided by the user which maps a function name with its pointer. The loader +provides an empty table so that the user need only provide additional entry +required by the relocator. + +In order to keep the size of the table to a minimum, the user can selectively +include only those functions that are expected to be used by the loader to +resolve all references. + +The following is an example of how to add an entry to the external references +table: + +CYG_LDR_TABLE_ENTRY( diag_printf_entry, "diag_printf", diag_printf ); + +The first parameter is a unique identifier, the second is a string containing +the name of the function, and the third is the pointer to the function itself. +The entries can be added anywhere in the file. + +The objelf.h file contains a number of macros that collect groups of +functions together as a convenient way to include blocks of +functionality. + + +-------------------------------------------------------------------------------- +Writing the relocator for a new architecture +-------------------------------------------------------------------------------- +A relocator for a new architecture must provide a function with the following +prototype: + +cyg_int32 +cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value ) + +The sym type is the type of relocation to apply. This value is architecture +dependent and it is obtained from the r_info field of the relocation entry. +The mem address is the memory location to relocate. The sym_value is the +value to use for the relocation. The size of the write operation is dependent +on the sym_type value. + +The relocate_xxx.h file must provide definitions for: + +1) the machine ELF type +2) the endianness of the architecture + ELFDATA2MSB : Big endian + ELFDATA2LSB : Little endian +3) The relocation type + Elf_Rela : With addend + Elf_Rel : Without addend + +An example of the definition for the PowerPC processor is the following: + +#define ELF_ARCH_MACHINE_TYPE 20 // PowerPC. +#define ELF_ARCH_ENDIANNESS ELFDATA2MSB // Big Endian. +#define ELF_ARCH_RELTYPE Elf_Rela // With addend. + +These definitions can be found in the relocate_ppc.h file. + +The user must also provide a way to flush the data and address caches. This +is architecture dependent and usually the macros to do this are already part +of the eCos HAL. + +-------------------------------------------------------------------------------- +CDL File +-------------------------------------------------------------------------------- + +The CDL file allows the selective compilation of the architecture dependent +file. If a new architecture is added, the CDL file must be updated to +include the architecture dependent files. + +-------------------------------------------------------------------------------- +Test program +-------------------------------------------------------------------------------- + +The 'tests' directory contains a simple/sample application that shows how to +use the object loader. The application loads a couple of symbols and runs +the functions pointed by those symbols. In particular, the second symbol is +a function which, in the library, is declared with the CYGBLD_ATTRIB_WEAK. If +the entry + +CYG_LDR_TABLE_ENTRY( weak_function_entry, "weak_function", weak_function ); + +is found in the application then the function in the application is called. +Otherwise, the function in the library is. + +The source code for the library used for this example can be found under the +'library' directory. + +The library shows a number of concepts, including external references and WEAK +references. The ubiquitous "twothreads' application is also included, and run +by the main application. Notice the initialization of the semaphore in the +library_open() call. + +The library can be compiled with the command + +<toolchain>-gcc -c -Wall -o hello.o hello.c + +and then be put into some file system and loaded. In the specific example +provided, the library was placed in the root directory of a FAT partition. +JFFS2 is also an option. + +If the CDL option CYGBLD_SERVICES_OBJLOADER_BUILD_TESTS is enabled, +then the test program and the library will be compiled automatically +and placed in the install tree bin directory. + +-------------------------------------------------------------------------------- +Final musings +-------------------------------------------------------------------------------- + +The cyg_ldr_open_library() call can be modified so that the user can use a +library that is already in memory, or one that must be retrieved via ftp or +tftp. In order to do this some functions must be added: + +- A function to open the file. In the simplest case of a file system, this + function would be a wrapper for fopen(). See loader_fs.c for a possible + implementation for a file system +- Function to read, seek and close the library. +- In case you have a statically allocated memory pool, you might want to + define your own cyg_ldr_malloc() and cyg_ldr_free(). Currently they are + defined as weak bindings to wrappers of the malloc() and free() functions + +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/include/elf.h @@ -0,0 +1,234 @@ +#ifndef __ELF_H__ +#define __ELF_H__ + +/* ================================================================= + * + * elf.f + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +typedef cyg_uint32 Elf32_Addr; +typedef cyg_uint16 Elf32_Half; +typedef cyg_uint32 Elf32_Off; +typedef cyg_int32 Elf32_Sword; +typedef cyg_uint32 Elf32_Word; + +#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; + +// The ELFCLASS* macros are the defined values of e_ident[EI_CLASS]. +#define ELFCLASSNONE 0 // Invalid class. +#define ELFCLASS32 1 // 32-bit objects. +#define ELFCLASS64 2 // 64-bit objects. + +// The ELFDATA* macros are the allowed values of e_ident[EI_DATA]. +#define ELFDATA2LSB 1 // Little Endian +#define ELFDATA2MSB 2 // Big Endian. + +// The ET_* macros define the values of the e_type field of the ElfXX_Ehdr +// structure. +#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. +#define ET_LOPROC 0xff00 // Processor-specific. + +// The ELFMAG* macros are the values of e_ident[EI_MAG0-4] +#define ELFMAG0 0x7f // magic number, byte 0 +#define ELFMAG1 'E' // magic number, byte 1 +#define ELFMAG2 'L' // magic number, byte 2 +#define ELFMAG3 'F' // magic number, byte 3 +#define ELFMAG "\177ELF" // magic string +#define SELFMAG 4 // magic string length + +#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 + +typedef struct +{ + Elf32_Word sh_name; // section name. + Elf32_Word sh_type; // SHT_... + Elf32_Word sh_flags; // SHF_... + Elf32_Addr sh_addr; // virtual address + Elf32_Off sh_offset; // file offset + Elf32_Word sh_size; // section size + Elf32_Word sh_link; // misc info + Elf32_Word sh_info; // misc info + Elf32_Word sh_addralign; // memory alignment + Elf32_Word sh_entsize; // entry size if table. +} Elf32_Shdr; + +// Symbols table entry. +typedef struct +{ + Elf32_Word st_name; // Symbol name (string tbl index). + Elf32_Addr st_value; // Symbol value. + Elf32_Word st_size; // Symbol size. + unsigned char st_info; // Symbol type and binding. + unsigned char st_other; // Symbol visibility. + Elf32_Half st_shndx; // Section index. +} Elf32_Sym; + +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 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 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 STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +// The ELF_STRING_xxx macros are names of common sections +#define ELF_STRING_bss ".bss" +#define ELF_STRING_hbss ".hbss" +#define ELF_STRING_sbss ".sbss" +#define ELF_STRING_tbss ".tbss" +#define ELF_STRING_data ".data" +#define ELF_STRING_hdata ".hdata" +#define ELF_STRING_sdata ".sdata" +#define ELF_STRING_sdata2 ".sdata2" +#define ELF_STRING_fini ".fini" +#define ELF_STRING_init ".init" +#define ELF_STRING_interp ".interp" +#define ELF_STRING_rodata ".rodata" +#define ELF_STRING_text ".text" +#define ELF_STRING_comment ".comment" +#define ELF_STRING_dynamic ".dynamic" +#define ELF_STRING_dynstr ".dynstr" +#define ELF_STRING_dynsym ".dynsym" +#define ELF_STRING_dlt ".dlt" +#define ELF_STRING_note ".note" +#define ELF_STRING_opd ".opd" +#define ELF_STRING_plt ".plt" +#define ELF_STRING_bss_rela ".rela.bss" +#define ELF_STRING_hbss_rela ".rela.hbss" +#define ELF_STRING_data_rela ".rela.data" +#define ELF_STRING_dlt_rela ".rela.dlt" +#define ELF_STRING_plt_rela ".rela.plt" +#define ELF_STRING_sdata_rela ".rela.sdata" +#define ELF_STRING_strtab ".strtab" +#define ELF_STRING_symtab ".symtab" +#define ELF_STRING_hash ".hash" +#define ELF_STRING_shstrtab ".shstrtab" +#define ELF_STRING_shsymtab ".shsymtab" +#define ELF_STRING_rela ".rela" +#define ELF_STRING_rel ".rel" + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) + +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0x0F) + + +#endif +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/include/loader_fs.h @@ -0,0 +1,60 @@ +#ifndef __LOADER_FS_H__ +#define __LOADER_FS_H__ + +/* ================================================================= + * + * loader_fs.c + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +size_t cyg_ldr_fs_read( PELF_OBJECT, size_t, size_t, void* ); +cyg_int32 cyg_ldr_fs_seek( PELF_OBJECT, cyg_uint32 ); +cyg_int32 cyg_ldr_fs_close( PELF_OBJECT ); + +#endif // __LOADER_FS_H__
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/include/objelf.h @@ -0,0 +1,557 @@ +#ifndef __OBJELF_H__ +#define __OBJELF_H__ + +/* ================================================================= + * + * objelf.h + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Contributors: nickg@ecoscentric.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +//============================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/objloader.h> + +//============================================================================== + +extern cyg_uint8 *cyg_ldr_last_error; + +//============================================================================== + +#define CYG_LDR_MODE_FILESYSTEM 0 +#define CYG_LDR_MODE_FTP 1 +#define CYG_LDR_MODE_TFTP 2 +#define CYG_LDR_MODE_MEMORY 3 +#define CYG_LDR_MODE_HTTP 4 + +//============================================================================== + +typedef struct ELF_OBJECT +{ + CYG_ADDRWORD ptr; + cyg_uint32 mode; + + size_t (*read)( struct ELF_OBJECT*, size_t, size_t, void* ); + cyg_int32 (*seek)( struct ELF_OBJECT*, cyg_uint32 ); + cyg_int32 (*close)( struct ELF_OBJECT* ); + + // This is the absolute address in memory where the library resides. + Elf32_Ehdr* p_elfhdr; + + // Start of the section header. + Elf32_Shdr* p_sechdr; + + cyg_int32 hdrndx_symtab; + cyg_int32 hdrndx_strtab; + + cyg_uint32 **sections; + +} ELF_OBJECT, *PELF_OBJECT; + + +//============================================================================== +// Debug functions. + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL != 0 +#define ELFDEBUG(a) diag_printf(a) +#else +#define ELFDEBUG(a) +#endif + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 +void cyg_ldr_print_section_data( PELF_OBJECT ); +void cyg_ldr_print_symbol_names( PELF_OBJECT ); +void cyg_ldr_print_rel_names( PELF_OBJECT ); +#endif + +//============================================================================== +// Internal functions + +cyg_int32 *cyg_ldr_load_elf_section( PELF_OBJECT, cyg_uint32 ); +void cyg_ldr_delete_elf_section( PELF_OBJECT, cyg_uint32 ); +cyg_int32 *cyg_ldr_section_address( PELF_OBJECT, cyg_uint32 ); +void* cyg_ldr_scan_file( PELF_OBJECT ); +cyg_int32 cyg_ldr_relocate_section( PELF_OBJECT, cyg_uint32 ); +void* cyg_ldr_find_symbol( void*, cyg_uint8* ); +void* cyg_ldr_symbol_address( PELF_OBJECT, cyg_uint32 ); +void* cyg_ldr_external_address( PELF_OBJECT, cyg_uint32 ); + +//============================================================================== +// User interface. + +PELF_OBJECT cyg_ldr_open_library( CYG_ADDRWORD, cyg_int32 ); +void cyg_ldr_close_library( void* ); +cyg_uint8* cyg_ldr_error( void ); +void* cyg_ldr_get_symbol( void*, char* ); + +PELF_OBJECT cyg_ldr_open_library_fs( cyg_uint8* ); +void cyg_ldr_close_library_fs( PELF_OBJECT ); + +//============================================================================== + +void *cyg_ldr_malloc( size_t ) CYGBLD_ATTRIB_WEAK; +void cyg_ldr_free( void * ) CYGBLD_ATTRIB_WEAK; + +//============================================================================== + +struct cyg_ldr_table_entry +{ + char *symbol_name; + void *handler; +} CYG_HAL_TABLE_TYPE; + +typedef struct cyg_ldr_table_entry cyg_ldr_table_entry; + +#define CYG_LDR_TABLE_ENTRY( __name, __symbol_name, __handler ) \ + cyg_ldr_table_entry __name CYG_HAL_TABLE_ENTRY( ldr_table ) = \ + { __symbol_name, __handler } + +//============================================================================== + +#define CYG_LDR_TABLE_KAPI_ALARM() \ +CYG_LDR_TABLE_ENTRY( cyg_alarm_create_entry, \ + "cyg_alarm_create", cyg_alarm_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_alarm_delete_entry, \ + "cyg_alarm_delete", cyg_alarm_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_alarm_initialize_entry, \ + "cyg_alarm_initialize", cyg_alarm_initialize ); \ +CYG_LDR_TABLE_ENTRY( cyg_alarm_get_times_entry, \ + "cyg_alarm_get_times", cyg_alarm_get_times ); \ +CYG_LDR_TABLE_ENTRY( cyg_alarm_enable_entry, \ + "cyg_alarm_enable", cyg_alarm_enable ); \ +CYG_LDR_TABLE_ENTRY( cyg_alarm_disable_entry, \ + "cyg_alarm_disable", cyg_alarm_disable ); + +#define CYG_LDR_TABLE_KAPI_CLOCK() \ +CYG_LDR_TABLE_ENTRY( cyg_clock_create_entry, \ + "cyg_clock_create", cyg_clock_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_clock_delete_entry, \ + "cyg_clock_delete", cyg_clock_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_clock_to_counter_entry, \ + "cyg_clock_to_counter", cyg_clock_to_counter ); \ +CYG_LDR_TABLE_ENTRY( cyg_clock_set_resolution_entry, \ + "cyg_clock_set_resolution", cyg_clock_set_resolution ); \ +CYG_LDR_TABLE_ENTRY( cyg_clock_get_resolution_entry, \ + "cyg_clock_get_resolution",cyg_clock_get_resolution ); \ +CYG_LDR_TABLE_ENTRY( cyg_real_time_clock_entry, \ + "cyg_real_time_clock", cyg_real_time_clock ); \ +CYG_LDR_TABLE_ENTRY( cyg_current_time_entry, \ + "cyg_current_time", cyg_current_time ); + +#define CYG_LDR_TABLE_KAPI_COND() \ +CYG_LDR_TABLE_ENTRY( cyg_cond_init_entry, \ + "cyg_cond_init", cyg_cond_init ); \ +CYG_LDR_TABLE_ENTRY( cyg_cond_destroy_entry, \ + "cyg_cond_destroy", cyg_cond_destroy ); \ +CYG_LDR_TABLE_ENTRY( cyg_cond_wait_entry, \ + "cyg_cond_wait", cyg_cond_wait ); \ +CYG_LDR_TABLE_ENTRY( cyg_cond_signal_entry, \ + "cyg_cond_signal", cyg_cond_signal ); \ +CYG_LDR_TABLE_ENTRY( cyg_cond_broadcast_entry, \ + "cyg_cond_broadcast", cyg_cond_broadcast ); \ +CYG_LDR_TABLE_ENTRY( cyg_cond_timed_wait_entry, \ + "cyg_cond_timed_wait", cyg_cond_timed_wait ); + +#define CYG_LDR_TABLE_KAPI_COUNTER() \ +CYG_LDR_TABLE_ENTRY( cyg_counter_create_entry, \ + "cyg_counter_create", cyg_counter_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_counter_delete_entry, \ + "cyg_counter_delete", cyg_counter_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_counter_current_value_entry, \ + "cyg_counter_current_value", cyg_counter_current_value ); \ +CYG_LDR_TABLE_ENTRY( cyg_counter_set_value_entry, \ + "cyg_counter_set_value", cyg_counter_set_value ); \ +CYG_LDR_TABLE_ENTRY( cyg_counter_tick_entry, \ + "cyg_counter_tick", cyg_counter_tick ); \ +CYG_LDR_TABLE_ENTRY( cyg_counter_multi_tick_entry, \ + "cyg_counter_multi_tick", cyg_counter_multi_tick ); + +#define CYG_LDR_TABLE_KAPI_EXCEPTIONS() \ +CYG_LDR_TABLE_ENTRY( cyg_exception_set_handler_entry, \ + "cyg_exception_set_handler", cyg_exception_set_handler ); \ +CYG_LDR_TABLE_ENTRY( cyg_exception_clear_handler_entry, \ + "cyg_exception_clear_handler", \ + cyg_exception_clear_handler ); \ +CYG_LDR_TABLE_ENTRY( cyg_exception_call_handler_entry, \ + "cyg_exception_call_handler", \ + cyg_exception_call_handler ); + +#define CYG_LDR_TABLE_KAPI_FLAG() \ +CYG_LDR_TABLE_ENTRY( cyg_flag_init_entry, \ + "cyg_flag_init", cyg_flag_init ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_destroy_entry, \ + "cyg_flag_destroy", cyg_flag_destroy ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_setbits_entry, \ + "cyg_flag_setbits", cyg_flag_setbits ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_maskbits_entry, \ + "cyg_flag_maskbits", cyg_flag_maskbits ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_wait_entry, \ + "cyg_flag_wait", cyg_flag_wait ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_timed_wait_entry, \ + "cyg_flag_timed_wait", cyg_flag_timed_wait ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_poll_entry, \ + "cyg_flag_poll", cyg_flag_poll ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_peek_entry, \ + "cyg_flag_peek", cyg_flag_peek ); \ +CYG_LDR_TABLE_ENTRY( cyg_flag_waiting_entry, \ + "cyg_flag_waiting", cyg_flag_waiting ); + +#define CYG_LDR_TABLE_KAPI_INTERRUPTS() \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_create_entry, \ + "cyg_interrupt_create", cyg_interrupt_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_delete_entry, \ + "cyg_interrupt_delete", cyg_interrupt_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_attach_entry, \ + "cyg_interrupt_attach", cyg_interrupt_attach ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_detach_entry, \ + "cyg_interrupt_detach", cyg_interrupt_detach ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_get_vsr_entry, \ + "cyg_interrupt_get_vsr", cyg_interrupt_get_vsr ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_set_vsr_entry, \ + "cyg_interrupt_set_vsr", cyg_interrupt_set_vsr ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_disable_entry, \ + "cyg_interrupt_disable", cyg_interrupt_disable ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_enable_entry, \ + "cyg_interrupt_enable", cyg_interrupt_enable ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_mask_entry, \ + "cyg_interrupt_mask", cyg_interrupt_mask ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_mask_intunsafe_entry, \ + "cyg_interrupt_mask_intunsafe", \ + cyg_interrupt_mask_intunsafe ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_unmask_entry, \ + "cyg_interrupt_unmask", cyg_interrupt_unmask ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_unmask_intunsafe_entry, \ + "cyg_interrupt_unmask_intunsafe", \ + cyg_interrupt_unmask_intunsafe ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_acknowledge_entry, \ + "cyg_interrupt_acknowledge", \ + cyg_interrupt_acknowledge ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_configure_entry, \ + "cyg_interrupt_configure", cyg_interrupt_configure ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_set_cpu_entry, \ + "cyg_interrupt_set_cpu", cyg_interrupt_set_cpu ); \ +CYG_LDR_TABLE_ENTRY( cyg_interrupt_get_cpu_entry, \ + "cyg_interrupt_get_cpu", cyg_interrupt_get_cpu ); + +#define CYG_LDR_TABLE_KAPI_MBOX() \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_create_entry, \ + "cyg_mbox_create", cyg_mbox_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_delete_entry, \ + "cyg_mbox_delete", cyg_mbox_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_get_entry, \ + "cyg_mbox_get", cyg_mbox_get ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_timed_get_entry, \ + "cyg_mbox_timed_get", cyg_mbox_timed_get ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_tryget_entry, \ + "cyg_mbox_tryget", cyg_mbox_tryget ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_peek_item_entry, \ + "cyg_mbox_peek_item", cyg_mbox_peek_item ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_put_entry, \ + "cyg_mbox_put", cyg_mbox_put ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_timed_put_entry, \ + "cyg_mbox_timed_put", cyg_mbox_timed_put ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_tryput_entry, \ + "cyg_mbox_tryput", cyg_mbox_tryput ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_peek_entry, \ + "cyg_mbox_peek", cyg_mbox_peek ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_waiting_to_get_entry, \ + "cyg_mbox_waiting_to_get_item", \ + cyg_mbox_waiting_to_get_item ); \ +CYG_LDR_TABLE_ENTRY( cyg_mbox_waiting_to_put_entry, \ + "cyg_mbox_waiting_to_put_item", \ + cyg_mbox_waiting_to_put_item ); + +#define CYG_LDR_TABLE_KAPI_MEMPOOL_FIX() \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_create_entry, \ + "cyg_mempool_fix_create", cyg_mempool_fix_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_delete_entry, \ + "cyg_mempool_fix_delete", cyg_mempool_fix_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_alloc_entry, \ + "cyg_mempool_fix_alloc", cyg_mempool_fix_alloc ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_timed_alloc_entry, \ + "cyg_mempool_fix_timed_alloc", \ + cyg_mempool_fix_timed_alloc ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_try_alloc_entry, \ + "cyg_mempool_fix_try_alloc", \ + cyg_mempool_fix_try_alloc ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_free_entry, \ + "cyg_mempool_fix_free", cyg_mempool_fix_free ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_waiting_entry, \ + "cyg_mempool_fix_waiting", cyg_mempool_fix_waiting ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_fix_get_info_entry, \ + "cyg_mempool_fix_get_info", cyg_mempool_fix_get_info ); + +#define CYG_LDR_TABLE_KAPI_MEMPOOL_VAR() \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_create_entry, \ + "cyg_mempool_var_create", cyg_mempool_var_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_delete_entry, \ + "cyg_mempool_var_delete", cyg_mempool_var_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_alloc_entry, \ + "cyg_mempool_var_alloc", cyg_mempool_var_alloc ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_timed_alloc_entry, \ + "cyg_mempool_var_timed_alloc", \ + cyg_mempool_var_timed_alloc ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_try_alloc_entry, \ + "cyg_mempool_var_try_alloc", \ + cyg_mempool_var_try_alloc ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_free_entry, \ + "cyg_mempool_var_free", cyg_mempool_var_free ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_waiting_entry, \ + "cyg_mempool_var_waiting", cyg_mempool_var_waiting ); \ +CYG_LDR_TABLE_ENTRY( cyg_mempool_var_get_info_entry, \ + "cyg_mempool_var_get_info", cyg_mempool_var_get_info ); + +#define CYG_LDR_TABLE_KAPI_MUTEX() \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_init_entry, \ + "cyg_mutex_init", cyg_mutex_init ); \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_destroy_entry, \ + "cyg_mutex_destroy", cyg_mutex_destroy ); \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_trylock_entry, \ + "cyg_mutex_trylock", cyg_mutex_trylock ); \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_unlock_entry, \ + "cyg_mutex_unlock", cyg_mutex_unlock ); \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_release_entry, \ + "cyg_mutex_release", cyg_mutex_release ); \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_set_ceiling_entry, \ + "cyg_mutex_set_ceiling", cyg_mutex_set_ceiling ); \ +CYG_LDR_TABLE_ENTRY( cyg_mutex_set_protocol_entry, \ + "cyg_mutex_set_protocol", cyg_mutex_set_protocol ); + +#define CYG_LDR_TABLE_KAPI_SCHEDULER() \ +CYG_LDR_TABLE_ENTRY( cyg_scheduler_start_entry, \ + "cyg_scheduler_start", cyg_scheduler_start ); \ +CYG_LDR_TABLE_ENTRY( cyg_scheduler_lock_entry, \ + "cyg_scheduler_lock", cyg_scheduler_lock ); \ +CYG_LDR_TABLE_ENTRY( cyg_scheduler_safe_lock_entry, \ + "cyg_scheduler_safe_lock", cyg_scheduler_safe_lock ); \ +CYG_LDR_TABLE_ENTRY( cyg_scheduler_unlock_entry, \ + "cyg_scheduler_unlock", cyg_scheduler_unlock ); \ +CYG_LDR_TABLE_ENTRY( cyg_scheduler_read_lock_entry, \ + "cyg_scheduler_read_lock", cyg_scheduler_read_lock ); \ + +#define CYG_LDR_TABLE_KAPI_SEMAPHORE() \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_init_entry, \ + "cyg_semaphore_init", cyg_semaphore_init ); \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_destroy_entry, \ + "cyg_semaphore_destroy", cyg_semaphore_destroy ); \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_wait_entry, \ + "cyg_semaphore_wait", cyg_semaphore_wait ); \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_timed_wait_entry, \ + "cyg_semaphore_timed_wait", cyg_semaphore_timed_wait ); \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_try_wait_entry, \ + "cyg_semaphore_try_wait", cyg_semaphore_try_wait ); \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_post_entry, \ + "cyg_semaphore_post", cyg_semaphore_post ); \ +CYG_LDR_TABLE_ENTRY( cyg_semaphore_peek_entry, \ + "cyg_semaphore_peek", cyg_semaphore_peek ); + +#define CYG_LDR_TABLE_KAPI_THREAD() \ +CYG_LDR_TABLE_ENTRY( cyg_thread_create_entry, \ + "cyg_thread_create", cyg_thread_create ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_exit_entry, \ + "cyg_thread_exit", cyg_thread_exit ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_delete_entry, \ + "cyg_thread_delete", cyg_thread_delete ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_suspend_entry, \ + "cyg_thread_suspend", cyg_thread_suspend ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_resume_entry, \ + "cyg_thread_resume", cyg_thread_resume ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_kill_entry, \ + "cyg_thread_kill", cyg_thread_kill ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_release_entry, \ + "cyg_thread_release", cyg_thread_release ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_yield_entry, \ + "cyg_thread_yield", cyg_thread_yield ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_self_entry, \ + "cyg_thread_self", cyg_thread_self ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_idle_thread_entry, \ + "cyg_thread_idle_thread", cyg_thread_idle_thread ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_set_priority_entry, \ + "cyg_thread_set_priority", cyg_thread_set_priority ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_priority_entry, \ + "cyg_thread_get_priority", cyg_thread_get_priority ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_current_priority_entry, \ + "cyg_thread_get_current_priority", \ + cyg_thread_get_current_priority ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_delay_entry, \ + "cyg_thread_delay", cyg_thread_delay ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_stack_base_entry, \ + "cyg_thread_get_stack_base", cyg_thread_get_stack_base ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_stack_size_entry, \ + "cyg_thread_get_stack_size", cyg_thread_get_stack_size ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_stack_usage_entry, \ + "cyg_thread_get_stack_usage", \ + cyg_thread_get_stack_usage ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_measure_stack_usage_entry, \ + "cyg_thread_measure_stack_usage", \ + cyg_thread_measure_stack_usage ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_new_data_index_entry, \ + "cyg_thread_new_data_index", cyg_thread_new_data_index ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_free_data_index_entry, \ + "cyg_thread_free_data_index", \ + cyg_thread_free_data_index ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_data_entry, \ + "cyg_thread_get_data", cyg_thread_get_data ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_get_data_ptr_entry, \ + "cyg_thread_get_data_ptr", cyg_thread_get_data_ptr ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_set_data_entry, \ + "cyg_thread_set_data", cyg_thread_set_data ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_add_destructor_entry, \ + "cyg_thread_add_destructor", cyg_thread_add_destructor ); \ +CYG_LDR_TABLE_ENTRY( cyg_thread_rem_destructor_entry, \ + "cyg_thread_rem_destructor", cyg_thread_rem_destructor ); + +#define CYG_LDR_TABLE_STRING() \ +CYG_LDR_TABLE_ENTRY( memchr_entry, "memchr", memchr ); \ +CYG_LDR_TABLE_ENTRY( memcmp_entry, "memcmp", memcmp ); \ +CYG_LDR_TABLE_ENTRY( memcpy_entry, "memcpy", memcpy ); \ +CYG_LDR_TABLE_ENTRY( memmove_entry, "memmove", memmove ); \ +CYG_LDR_TABLE_ENTRY( memset_entry, "memset", memset ); \ +CYG_LDR_TABLE_ENTRY( strcpy_entry, "strcpy", strcpy ); \ +CYG_LDR_TABLE_ENTRY( strncpy_entry, "strncpy", strncpy ); \ +CYG_LDR_TABLE_ENTRY( strcat_entry, "strcat", strcat ); \ +CYG_LDR_TABLE_ENTRY( strncat_entry, "strncat", strncat ); \ +CYG_LDR_TABLE_ENTRY( strchr_entry, "strchr", strchr ); \ +CYG_LDR_TABLE_ENTRY( strrchr_entry, "strrchr", strrchr ); \ +CYG_LDR_TABLE_ENTRY( strcoll_entry, "strcoll", strcoll ); \ +CYG_LDR_TABLE_ENTRY( strlen_entry, "strlen", strlen ); \ +CYG_LDR_TABLE_ENTRY( strcmp_entry, "strcmp", strcmp ); \ +CYG_LDR_TABLE_ENTRY( strncmp_entry, "strncmp", strncmp ); \ +CYG_LDR_TABLE_ENTRY( strcspn_entry, "strcspn", strcspn ); \ +CYG_LDR_TABLE_ENTRY( strerror_entry, "strerror", strerror ); \ +CYG_LDR_TABLE_ENTRY( strpbrk_entry, "strpbrk", strpbrk ); \ +CYG_LDR_TABLE_ENTRY( strspn_entry, "strspn", strspn ); \ +CYG_LDR_TABLE_ENTRY( strstr_entry, "strstr", strstr ); \ +CYG_LDR_TABLE_ENTRY( strtok_entry, "strtok", strtok ); \ +CYG_LDR_TABLE_ENTRY( strxfrm_entry, "strxfrm", strxfrm ); + +#define CYG_LDR_TABLE_STDIO() \ +CYG_LDR_TABLE_ENTRY( clearerr_entry, "clearerr", clearerr ); \ +CYG_LDR_TABLE_ENTRY( fclose_entry, "fclose", fclose ); \ +CYG_LDR_TABLE_ENTRY( feof_entry, "feof", feof ); \ +CYG_LDR_TABLE_ENTRY( ferror_entry, "ferror", ferror ); \ +CYG_LDR_TABLE_ENTRY( fflush_entry, "fflush", fflush ); \ +CYG_LDR_TABLE_ENTRY( fgetc_entry, "fgetc", fgetc ); \ +CYG_LDR_TABLE_ENTRY( fgetpos_entry, "fgetpos", fgetpos ); \ +CYG_LDR_TABLE_ENTRY( fgets_entry, "fgets", fgets ); \ +CYG_LDR_TABLE_ENTRY( fopen_entry, "fopen", fopen ); \ +CYG_LDR_TABLE_ENTRY( fprintf_entry, "fprintf", fprintf ); \ +CYG_LDR_TABLE_ENTRY( fputc_entry, "fputc", fputc ); \ +CYG_LDR_TABLE_ENTRY( fputchar_entry, "fputchar", fputchar ); \ +CYG_LDR_TABLE_ENTRY( fputs_entry, "fputs", fputs ); \ +CYG_LDR_TABLE_ENTRY( fread_entry, "fread", fread ); \ +CYG_LDR_TABLE_ENTRY( freopen_entry, "freopen", freopen ); \ +CYG_LDR_TABLE_ENTRY( fscanf_entry, "fscanf", fscanf ); \ +CYG_LDR_TABLE_ENTRY( fseek_entry, "fseek", fseek ); \ +CYG_LDR_TABLE_ENTRY( fsetpos_entry, "fsetpos", fsetpos ); \ +CYG_LDR_TABLE_ENTRY( ftell_entry, "ftell", ftell ); \ +CYG_LDR_TABLE_ENTRY( fwrite_entry, "fwrite", fwrite ); \ +CYG_LDR_TABLE_ENTRY( fgetc_entry, "fgetc", fgetc ); \ +CYG_LDR_TABLE_ENTRY( fgetchar_entry, "fgetchar", fgetchar ); \ +CYG_LDR_TABLE_ENTRY( fgets_entry, "fgets", fgets ); \ +CYG_LDR_TABLE_ENTRY( fgetw_entry, "fgetw", fgetw ); \ +CYG_LDR_TABLE_ENTRY( perror_entry, "perror", perror ); \ +CYG_LDR_TABLE_ENTRY( printf_entry, "printf", printf ); \ +CYG_LDR_TABLE_ENTRY( putc_entry, "putc", putc ); \ +CYG_LDR_TABLE_ENTRY( putchar_entry, "putchar", putchar ); \ +CYG_LDR_TABLE_ENTRY( puts_entry, "puts", puts ); \ +CYG_LDR_TABLE_ENTRY( putw_entry, "putw", putw ); \ +CYG_LDR_TABLE_ENTRY( remove_entry, "remove", remove ); \ +CYG_LDR_TABLE_ENTRY( rename_entry, "rename", rename ); \ +CYG_LDR_TABLE_ENTRY( rewind_entry, "rewind", rewind ); \ +CYG_LDR_TABLE_ENTRY( scanf_entry, "scanf", scanf ); \ +CYG_LDR_TABLE_ENTRY( setbuf_entry, "setbuf", setbuf ); \ +CYG_LDR_TABLE_ENTRY( setvbuf_entry, "setvbuf", setvbuf ); \ +CYG_LDR_TABLE_ENTRY( sprintf_entry, "sprintf", sprintf ); \ +CYG_LDR_TABLE_ENTRY( sscanf_entry, "sscanf", sscanf ); \ +CYG_LDR_TABLE_ENTRY( tmpfile_entry, "tmpfile", tmpfile ); \ +CYG_LDR_TABLE_ENTRY( tmpnam_entry, "tmpnam", tmpnam ); \ +CYG_LDR_TABLE_ENTRY( ungetc_entry, "ungetc", ungetc ); + +#define CYG_LDR_TABLE_INFRA_DIAG() \ +CYG_LDR_TABLE_ENTRY( diag_init_entry, "diag_init", diag_init ); \ +CYG_LDR_TABLE_ENTRY( diag_write_char_entry, \ + "diag_write_char", diag_write_char ); \ +CYG_LDR_TABLE_ENTRY( diag_write_string_entry, \ + "diag_write_string", diag_write_string ); \ +CYG_LDR_TABLE_ENTRY( diag_write_dec_entry, \ + "diag_write_dec", diag_write_dec ); \ +CYG_LDR_TABLE_ENTRY( diag_write_hex_entry, \ + "diag_write_hex", diag_write_hex ); \ +CYG_LDR_TABLE_ENTRY( diag_dump_buf_entry, \ + "diag_dump_buf", diag_dump_buf ); \ +CYG_LDR_TABLE_ENTRY( diag_dump_buf_32bit_entry, \ + "diag_dump_buf_32bit", diag_dump_buf_32bit ); \ +CYG_LDR_TABLE_ENTRY( diag_dump_buf_16bit_entry, \ + "diag_dump_buf_16bit", diag_dump_buf_16bit ); \ +CYG_LDR_TABLE_ENTRY( __printf_fun_entry, \ + "__printf_fun", __printf_fun ); \ +CYG_LDR_TABLE_ENTRY( diag_vdump_buf_with_offset_entry, \ + "diag_vdump_buf_with_offset", \ + diag_vdump_buf_with_offset ); \ +CYG_LDR_TABLE_ENTRY( diag_dump_buf_with_offset_entry, \ + "diag_dump_buf_with_offset", \ + diag_dump_buf_with_offset ); \ +CYG_LDR_TABLE_ENTRY( diag_dump_buf_with_offset_32bit_entry, \ + "diag_dump_buf_with_offset_32bit", \ + diag_dump_buf_with_offset_32bit ); \ +CYG_LDR_TABLE_ENTRY( diag_dump_buf_with_offset_16bit_entry, \ + "diag_dump_buf_with_offset_16bit", \ + diag_dump_buf_with_offset_16bit ); \ +CYG_LDR_TABLE_ENTRY( diag_printf_entry, "diag_printf", diag_printf ); \ +CYG_LDR_TABLE_ENTRY( diag_init_putc_entry, "diag_init_putc", diag_init_putc ); \ +CYG_LDR_TABLE_ENTRY( diag_sprintf_entry, "diag_sprintf", diag_sprintf ); \ +CYG_LDR_TABLE_ENTRY( diag_snprintf_entry, "diag_snprintf", diag_snprintf ); \ +CYG_LDR_TABLE_ENTRY( diag_vsprintf_entry, "diag_vsprintf", diag_vsprintf ); \ +CYG_LDR_TABLE_ENTRY( diag_vprintf_entry, "diag_vprintf", diag_vprintf ); + +//============================================================================== +#endif +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/include/relocate_ppc.h @@ -0,0 +1,132 @@ +#ifndef __RELOCATE_PPC_H__ +#define __RELOCATE_PPC_H__ + +/* ================================================================= + * + * relocate_ppc.h + * + * Architecture dependent relocation routines for the PowerPC + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#define Elf_Rel 0 +#define Elf_Rela 1 +#define ELF_ARCH_MACHINE_TYPE 20 // PowerPC. +#define ELF_ARCH_ENDIANNESS ELFDATA2MSB +#define ELF_ARCH_RELTYPE Elf_Rela + +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 // 32bit absolute address +#define R_PPC_ADDR24 2 // 26bit address, 2 bits ignored. +#define R_PPC_ADDR16 3 // 16bit absolute address +#define R_PPC_ADDR16_LO 4 // lower 16bit of absolute address +#define R_PPC_ADDR16_HI 5 // high 16bit of absolute address +#define R_PPC_ADDR16_HA 6 // adjusted high 16bit +#define R_PPC_ADDR14 7 // 16bit address, 2 bits ignored +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 // PC relative 26 bit +#define R_PPC_REL14 11 // PC relative 16 bit +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +// Keep this the last entry. +#define R_PPC_NUM 37 + +// The remaining relocs are from the Embedded ELF ABI, and are not +// in the SVR4 ELF ABI. +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 // 16 bit offset in SDA +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 // 16 bit relative offset in SDA + +// From the Elf PPC spec. +#define _lo_(x) (x & 0xFFFF) +#define _hi_(x) ((x >> 16) & 0xFFFF) +#define _ha_(x) (((x >> 16)+((x & 0x8000) ? 1 : 0)) & 0xFFFF) + +void cyg_ldr_flush_cache( void ); +cyg_int32 cyg_ldr_relocate( cyg_int32, cyg_uint32, cyg_int32 ); + +#endif //__RELOCATE_PPC_H__
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/src/loader_fs.c @@ -0,0 +1,123 @@ +/* ================================================================= + * + * loader_fs.c + * + * Routines to read a library from a file system. + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Contributors: nickg@ecoscentric.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#include <cyg/infra/diag.h> // For diagnostic printing. +#include <pkgconf/io_fileio.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <pkgconf/objloader.h> +#include <cyg/objloader/elf.h> +#include <cyg/objloader/objelf.h> +#include <cyg/objloader/loader_fs.h> + +size_t +cyg_ldr_fs_read( PELF_OBJECT p, size_t s, size_t n, void *mem ) +{ + return fread( mem, s, n, (FILE*)p->ptr ); +} + +cyg_int32 +cyg_ldr_fs_seek( PELF_OBJECT p, cyg_uint32 offs ) +{ + return fseek( (FILE*)p->ptr, offs, SEEK_SET ); +} + +cyg_int32 +cyg_ldr_fs_close( PELF_OBJECT p ) +{ + return fclose( (FILE*)p->ptr ); +} + +PELF_OBJECT +cyg_ldr_open_library_fs( cyg_uint8 *ptr ) +{ + PELF_OBJECT e_obj; + FILE *fp; + + fp = fopen( ptr, "rb" ); + if ( fp == 0 ) + { + cyg_ldr_last_error = "FILE NOT FOUND"; + return (void*)0; + } + + // Create a file object to keep track of this library. + e_obj = (PELF_OBJECT)malloc( sizeof( ELF_OBJECT ) ); + CYG_ASSERT( e_obj != 0, "Cannot malloc() e_obj" ); + if ( e_obj == 0 ) + { + cyg_ldr_last_error = "ERROR IN MALLOC"; + fclose( fp ); + return (void*)0; + } + memset( e_obj, 0, sizeof( ELF_OBJECT ) ); + e_obj->ptr = (CYG_ADDRWORD)fp; + e_obj->mode = CYG_LDR_MODE_FILESYSTEM; + + // Handlers for the file system open. + e_obj->read = cyg_ldr_fs_read; + e_obj->seek = cyg_ldr_fs_seek; + e_obj->close = cyg_ldr_fs_close; + return e_obj; +} + +void +cyg_ldr_close_library_fs( PELF_OBJECT p ) +{ +} +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/src/objelf.c @@ -0,0 +1,397 @@ +/* ================================================================= + * + * objelf.c + * + * Relocation routine for eCos loader. + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Contributors: nickg@ecoscentric.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#include <cyg/infra/diag.h> // For diagnostic printing. +#include <pkgconf/io_fileio.h> +#include <cyg/hal/hal_tables.h> +#include <stdio.h> + +#include <pkgconf/objloader.h> +#include <cyg/objloader/elf.h> +#include <cyg/objloader/objelf.h> + +CYG_HAL_TABLE_BEGIN( cyg_ldr_table, ldr_table ); +CYG_HAL_TABLE_END( cyg_ldr_table_end, ldr_table ); + +__externC cyg_ldr_table_entry cyg_ldr_table[]; +__externC cyg_ldr_table_entry cyg_ldr_table_end[]; + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 +void +cyg_ldr_print_section_data( PELF_OBJECT p ) +{ + cyg_int32 i; + cyg_uint8 strname[32]; + cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->p_elfhdr->e_shstrndx]; + + diag_printf( "\n\nSection Headers:\n" ); + diag_printf( "[Nr] Name Addr Offset Size Info\n" ); + for ( i = 0; i < p->p_elfhdr->e_shnum; i++ ) + { + sprintf( strname, "%s", p_strtab + p->p_sechdr[i].sh_name ); + while ( strlen( strname ) < 20 ) + strcat( strname, " " ); + diag_printf( "[%02d] %s %08X %08X %08X %08X\n", + i, + strname, + p->p_sechdr[i].sh_addr, + p->p_sechdr[i].sh_offset, + p->p_sechdr[i].sh_size, + p->p_sechdr[i].sh_info ); + } + diag_printf( "\n" ); +} + +void +cyg_ldr_print_symbol_names( PELF_OBJECT p ) +{ + cyg_int32 i, symtab_entries; + Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab]; + cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->hdrndx_strtab]; + cyg_uint8 strname[32]; + + // Total number of entries in the symbol table. + symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size / + p->p_sechdr[p->hdrndx_symtab].sh_entsize; + diag_printf( "Num Value Size Ndx Name\n" ); + for ( i = 1; i < symtab_entries; i++ ) + { + sprintf( strname, "%d", i ); + while ( strlen( strname ) < 5 ) + strcat( strname, " " ); + diag_printf( strname ); + + sprintf( strname, + "%08X %d", + p_symtab[i].st_value, + p_symtab[i].st_size ); + while ( strlen( strname ) < 15 ) + strcat( strname, " " ); + diag_printf( strname ); + + sprintf( strname, "%d", p_symtab[i].st_shndx ); + while ( strlen( strname ) < 6 ) + strcat( strname, " " ); + diag_printf( strname ); + + strncpy( strname, + p_strtab + p_symtab[i].st_name, + sizeof( strname ) - 1 ); + strname[strlen( p_strtab + p_symtab[i].st_name )] = '\0'; + diag_printf( strname ); + diag_printf( "\n" ); + } +} + +void +cyg_ldr_print_rel_names( PELF_OBJECT p ) +{ + cyg_int32 i, j, r_entries, sym_index; + Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab]; + cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->hdrndx_strtab]; + cyg_uint8 *p_shstrtab = (cyg_uint8*)p->sections[p->p_elfhdr->e_shstrndx]; +#if ELF_ARCH_RELTYPE == Elf_Rela + Elf32_Rela* p_rela; +#else + Elf32_Rel* p_rel; +#endif + cyg_uint8 strname[32]; + + for ( i = 1; i < p->p_elfhdr->e_shnum; i++ ) + { + if ( ( p->p_sechdr[i].sh_type == SHT_REL ) || + ( p->p_sechdr[i].sh_type == SHT_RELA ) ) + { + // Calculate the total number of entries in the .rela section. + r_entries = p->p_sechdr[i].sh_size / p->p_sechdr[i].sh_entsize; + + diag_printf( "\n\nSymbols at: %s\n\n", + p_shstrtab + p->p_sechdr[i].sh_name ); +#if ELF_ARCH_RELTYPE == Elf_Rela + p_rela = (Elf32_Rela*)cyg_ldr_load_elf_section( p, i ); + printf( "Offset Info Name [+ Addend]\n" ); +#else + p_rel = (Elf32_Rel*)cyg_ldr_load_elf_section( p, i ); + printf( "Offset Info Name\n" ); +#endif + + for ( j = 0; j < r_entries; j++ ) + { + sprintf( strname, + "%08X %08X ", + p_rela[j].r_offset, + p_rela[j].r_info ); + + diag_printf( strname ); + + cyg_uint8 sym_type = ELF32_R_SYM( p_rela[j].r_info ); + if ( strlen ( p_strtab + p_symtab[sym_type].st_name ) > 0 ) + diag_printf( p_strtab + p_symtab[sym_type].st_name ); + else + { + // If the symbol name is not available, then print + // the name of the section. + sym_index = p_symtab[sym_type].st_shndx; + diag_printf( p_shstrtab + p->p_sechdr[sym_index].sh_name ); + } +#if ELF_ARCH_RELTYPE == Elf_Rela + if ( p_rela[j].r_addend != 0 ) + diag_printf( " + %08X", p_rela[j].r_addend ); +#endif + diag_printf( "\n" ); + } + // After all the printing is done, the relocation table can + // be dumped. + cyg_ldr_delete_elf_section( p, i ); + } + } +} +#endif // DEBUG_PRINT + +static void +*cyg_ldr_local_address( PELF_OBJECT p, cyg_uint32 sym_index ) +{ + cyg_uint32 data_sec, addr; + Elf32_Sym *p_symtab; + + p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab ); + + // Find out the section number in which the data for this symbol is + // located. + data_sec = p_symtab[sym_index].st_shndx; + + // From the section number we get the start of the memory area in + // memory. + addr = (cyg_uint32)cyg_ldr_section_address( p, data_sec ); + + // And now return the address of the data. + return (void*)( addr + p_symtab[sym_index].st_value); +} + +static void +*cyg_ldr_external_address( PELF_OBJECT p, cyg_uint32 sym_index ) +{ + cyg_uint8* tmp2; + Elf32_Sym *p_symtab; + cyg_uint8 *p_strtab; + cyg_ldr_table_entry *entry = cyg_ldr_table; + + + p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab ); + p_strtab = (cyg_uint8*)cyg_ldr_section_address( p, p->hdrndx_strtab ); + + // This is the name of the external reference to search. + tmp2 = p_strtab + p_symtab[sym_index].st_name; + while ( entry != cyg_ldr_table_end ) + { + if ( !strcmp( (const char*)tmp2, entry->symbol_name ) ) + return entry->handler; + entry++; + } + + // Symbol not found. + return 0; +} + +// input: +// p : Pointer to the elf file object +// sym_index : Index of the symbol to be searched (in the SYMTAB) +// +// out: +// 0 : Symbol not found +// Other : Address of the symbol in absolute memory. +void +*cyg_ldr_symbol_address( PELF_OBJECT p, cyg_uint32 sym_index ) +{ + cyg_uint32 addr; + cyg_uint8 sym_info; + Elf32_Sym *p_symtab; + + p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab ); + sym_info = p_symtab[sym_index].st_info; + + switch ( ELF32_ST_TYPE( sym_info ) ) + { + case STT_NOTYPE: + case STT_FUNC: + case STT_OBJECT: + switch ( ELF32_ST_BIND( sym_info ) ) + { + case STB_LOCAL: + case STB_GLOBAL: + if ( p_symtab[sym_index].st_shndx == SHN_UNDEF ) + return cyg_ldr_external_address( p, sym_index ); + else + return cyg_ldr_local_address( p, sym_index ); + case STB_WEAK: + addr = (cyg_uint32)cyg_ldr_external_address( p, sym_index ); + if ( addr != 0 ) + return (void*)addr; + else + return cyg_ldr_local_address( p, sym_index ); + default: + return 0; + } + break; + case STT_SECTION: + // Return the starting address of a section, given its index. + return (void*)cyg_ldr_section_address( p, + p_symtab[sym_index].st_shndx ); + default: + return 0; + } +} + +// Loads the relocation information, relocates, and dumps the relocation +// information once the process is complete. +cyg_int32 +cyg_ldr_relocate_section( PELF_OBJECT p, cyg_uint32 r_shndx ) +{ + cyg_int32 i, rc; + cyg_uint32 r_entries, r_target_shndx, r_target_addr; + cyg_uint32 sym_value, sym_index; + Elf32_Addr r_offset; + Elf32_Word r_type; + Elf32_Sword r_addend; +#if ELF_ARCH_RELTYPE == Elf_Rela + Elf32_Rela* p_rela = (Elf32_Rela*)cyg_ldr_load_elf_section( p, r_shndx ); +#else + Elf32_Rel* p_rel = (Elf32_Rel*)cyg_ldr_load_elf_section( p, r_shndx ); +#endif + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + Elf32_Sym *p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, + p->hdrndx_symtab ); + cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address( p, + p->hdrndx_strtab ); + cyg_uint8 *p_shstrtab = (cyg_uint8*)cyg_ldr_section_address( p, + p->p_elfhdr->e_shstrndx ); +#endif + + // Now we can get the address of the contents of the section to modify. + r_target_shndx = p->p_sechdr[r_shndx].sh_info; + r_target_addr = (cyg_uint32)cyg_ldr_section_address( p, r_target_shndx ); + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + diag_printf( "Relocating section \"%s\"\n", + p_shstrtab + p->p_sechdr[r_target_shndx].sh_name ); +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 + diag_printf( "Ndx Type Offset Name\"\n" ); +#endif +#endif + + // Perform relocatation for each of the members of this table. + r_entries = p->p_sechdr[r_shndx].sh_size / p->p_sechdr[r_shndx].sh_entsize; + for ( i = 0; i < r_entries; i++ ) + { +#if ELF_ARCH_RELTYPE == Elf_Rela + r_offset = p_rela[i].r_offset; + r_type = ELF32_R_TYPE( p_rela[i].r_info ); + sym_index = ELF32_R_SYM( p_rela[i].r_info ); + r_addend = p_rela[i].r_addend; +#else + r_offset = p_rel[i].r_offset; + r_type = ELF32_R_TYPE( p_rel[i].r_info ); + sym_index = ELF32_R_SYM( p_rel[i].r_info ); + r_addend = 0; +#endif + + sym_value = (cyg_uint32)cyg_ldr_symbol_address( p, sym_index ); + if ( sym_value == 0 ) + { +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + diag_printf( "Unknown symbol value: %s Index: %d\n", + p_strtab + p_symtab[sym_index].st_name, + sym_index ); +#endif + return -1; + } + + // This is architecture dependent, and deals with whether we have + // '.rel' or '.rela' sections. +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 + diag_printf( "%04X %04X %08X ", + sym_index, + r_type, + r_offset ); + if ( strlen ( p_strtab + p_symtab[sym_index].st_name ) > 0 ) + diag_printf( p_strtab + p_symtab[sym_index].st_name ); + else + { + // If the symbol name is not available, then print + // the name of the section. + cyg_uint32 sec_ndx = p_symtab[sym_index].st_shndx; + diag_printf( p_shstrtab + p->p_sechdr[sec_ndx].sh_name ); + } + diag_printf( "\n" ); +#endif + rc = cyg_ldr_relocate( r_type, + r_target_addr + r_offset, + sym_value + r_addend ); + if ( rc != 0 ) + { +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + diag_printf( "Relocation error: Cannot find symbol: %s\n", + p_strtab + p_symtab[sym_index].st_name ); +#endif + return -1; + } + } + + // After the relocation is done, the relocation table can be dumped. + cyg_ldr_delete_elf_section( p, r_shndx ); + return 0; +} +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/src/objloader.c @@ -0,0 +1,462 @@ +/* ================================================================= + * + * objelf.c + * + * An object loader for eCos + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Contributors: nickg@ecoscentric.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#include <cyg/infra/diag.h> // For diagnostic printing. +#include <cyg/infra/cyg_ass.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <pkgconf/objloader.h> +#include <cyg/objloader/elf.h> +#include <cyg/objloader/objelf.h> +#include <cyg/objloader/loader_fs.h> + +cyg_uint8 *cyg_ldr_last_error; + +void *cyg_ldr_malloc( size_t ) CYGBLD_ATTRIB_WEAK; +void +*cyg_ldr_malloc( size_t s ) +{ + return malloc( s ); +} + +void cyg_ldr_free( void * ) CYGBLD_ATTRIB_WEAK; +void +cyg_ldr_free( void *s ) +{ + free( s ); +} + +void +cyg_ldr_delete_elf_section( PELF_OBJECT p, cyg_uint32 idx ) +{ + cyg_ldr_free( p->sections[idx] ); + p->sections[idx] = 0; +} + +// Frees all the memory allocated for a particular ELF object. Also calls +// the close() function to close files or sockets, and finally frees up +// the ELF object altogether. +static void +cyg_ldr_free_elf_object( PELF_OBJECT p ) +{ + cyg_int32 i; + + for ( i = 0; i < p->p_elfhdr->e_shnum + 1; i++ ) + if ( p->sections[i] ) + cyg_ldr_delete_elf_section( p, i ); + + if ( p->sections != 0 ) + cyg_ldr_free( p->sections ); + + if ( p->p_sechdr != 0 ) + cyg_ldr_free( p->p_sechdr ); + + if ( p->p_elfhdr != 0 ) + cyg_ldr_free( p->p_elfhdr ); + + p->close( p ); + cyg_ldr_free( p ); +} + +static cyg_uint32 +cyg_ldr_find_common_size( PELF_OBJECT p ) +{ + cyg_int32 i, symtab_entries, common_size = 0; + Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab]; + + // Total number of entries in the symbol table. + symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size / + p->p_sechdr[p->hdrndx_symtab].sh_entsize; + for ( i = 1; i < symtab_entries; i++ ) + if ( p_symtab[i].st_shndx == SHN_COMMON ) + { + // In the case of an SHN_COMMON symbol the st_value field holds + // alignment constraints. + cyg_uint32 boundary = p_symtab[i].st_value - 1; + + // Calculate the next byte boundary. + common_size = ( common_size + boundary ) & ~boundary; + common_size += p_symtab[i].st_size; + } + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + diag_printf( "common_size = %d\n", common_size ); +#endif + return common_size; +} + +// Allocates memory and loads the contents of a specific ELF section. +// Returns the address of the newly allocated memory, of 0 for any error. +cyg_int32 +*cyg_ldr_load_elf_section( PELF_OBJECT p, cyg_uint32 idx ) +{ + cyg_uint32 *addr; + + addr = cyg_ldr_malloc( p->p_sechdr[idx].sh_size ); + CYG_ASSERT( addr != 0, "Cannot malloc() section" ); + if ( addr == 0 ) + { + cyg_ldr_last_error = "ERROR IN MALLOC"; + return (void*)0; + } + p->seek( p, p->p_sechdr[idx].sh_offset ); + p->read( p, sizeof( char ), p->p_sechdr[idx].sh_size, addr ); + return addr; +} + +// Returns the starting address of a section. If the section is not already +// loaded in memory, area for it will be allocated and the section will be +// loaded. +cyg_int32 +*cyg_ldr_section_address( PELF_OBJECT p, cyg_uint32 idx ) +{ + if ( p->sections[idx] == 0 ) + p->sections[idx] = cyg_ldr_load_elf_section( p, idx ); + + return p->sections[idx]; +} + +void +*cyg_ldr_find_symbol( void* handle, cyg_uint8* sym_name ) +{ + PELF_OBJECT p = (PELF_OBJECT)handle; + cyg_uint8* tmp2; + cyg_int32 i, symtab_entries; + cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->hdrndx_strtab]; + Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab]; + + symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size / + p->p_sechdr[p->hdrndx_symtab].sh_entsize; + + for ( i = 0; i < symtab_entries; i++ ) + { + tmp2 = p_strtab + p_symtab[i].st_name; + if ( !strcmp( tmp2, sym_name ) ) + return cyg_ldr_symbol_address( p, i ); + } + + // Symbol not found. + cyg_ldr_last_error = "SYMBOL NOT FOUND"; + return 0; +} + +static cyg_uint8 +*cyg_ldr_sanity_check( PELF_OBJECT p ) +{ + if ( ( p->p_elfhdr->e_ident[EI_MAG0] != ELFMAG0 ) || + ( p->p_elfhdr->e_ident[EI_MAG1] != ELFMAG1 ) || + ( p->p_elfhdr->e_ident[EI_MAG2] != ELFMAG2 ) || + ( p->p_elfhdr->e_ident[EI_MAG3] != ELFMAG3 ) || + ( p->p_elfhdr->e_ident[EI_CLASS] != ELFCLASS32 ) ) + return "INVALID ELF HEADER"; + + // We only work with relocatable files. No dynamic linking. + if ( p->p_elfhdr->e_type != ET_REL ) + return "NOT RELOCATABLE"; + + // These #defines are sitting in the hal. + if ( p->p_elfhdr->e_machine != ELF_ARCH_MACHINE_TYPE ) + return "INVALID ARCHITECTURE"; + + if ( p->p_elfhdr->e_ident[EI_DATA] != ELF_ARCH_ENDIANNESS ) + return "INVALID ENDIAN"; + return 0; } + +// Load only the ELF header and the sections header. These are the only +// sections loaded during library initialization. All the other sections +// will be loaded on demand when needed during the relocation process and, +// when possible, dumped after use. +static cyg_int32 +cyg_ldr_load_sections( PELF_OBJECT p ) +{ + cyg_uint8 *error_string; + cyg_int32 idx; + + // Load the ELF header. + p->p_elfhdr = (Elf32_Ehdr*)cyg_ldr_malloc( sizeof( Elf32_Ehdr ) ); + CYG_ASSERT( p->p_elfhdr != 0, "Cannot malloc() p->p_elfhdr" ); + if ( p->p_elfhdr == 0 ) + return -1; + p->seek( p, 0 ); + p->read( p, sizeof( char ), sizeof( Elf32_Ehdr ), p->p_elfhdr ); + error_string = cyg_ldr_sanity_check( p ); + if ( error_string != 0 ) + { + cyg_ldr_last_error = "ERROR IN ELF HEADER"; + return -1; + } + + // Allocate an array that can hold an address to all the section of this + // library. This is not strictly optimal, since some sections do not + // need to be loaded all the time. Allocate an extra pointer for the + // COMMON area. + p->sections = cyg_ldr_malloc( ( p->p_elfhdr->e_shnum + 1 ) * + sizeof( cyg_uint32 ) ); + CYG_ASSERT( p->sections != 0, "Cannot malloc() p->sections" ); + if ( p->sections == 0 ) + { + cyg_ldr_last_error = "ERROR IN MALLOC"; + return -1; + } + memset( p->sections, 0, ( p->p_elfhdr->e_shnum + 1 ) * + sizeof( cyg_uint32 ) ); + + // Now that the header is loaded, load the sections header. + p->p_sechdr = (Elf32_Shdr*)cyg_ldr_malloc( + p->p_elfhdr->e_shnum * p->p_elfhdr->e_shentsize ); + CYG_ASSERT( p->p_sechdr != 0, "Cannot malloc() p->p_sechdr" ); + if ( p->p_sechdr == 0 ) + { + cyg_ldr_last_error = "ERROR IN MALLOC"; + return -1; + } + p->seek( p, p->p_elfhdr->e_shoff ); + p->read( p, p->p_elfhdr->e_shentsize, p->p_elfhdr->e_shnum, p->p_sechdr ); + + // Load the section header string table. This is a byte oriented table, + // so alignment is not an issue. + idx = p->p_elfhdr->e_shstrndx; + p->sections[idx] = cyg_ldr_load_elf_section( p, idx ); + return 0; +} + +PELF_OBJECT +cyg_ldr_open_library( CYG_ADDRWORD ptr, cyg_int32 mode ) +{ + Elf32_Sym *p_symtab; + cyg_uint8 *p_shstrtab; + PELF_OBJECT e_obj; + int (*fn)(void); + cyg_int32 i, rc, symtab_entries; + cyg_uint32 common_size; + + // In the future there might be a switch() (against 'mode') that calls an + // open function other than cyg_ldr_open_library_fs(). These function + // fetch and open a library using ftp, http or libraries that are already + // in ROM. + e_obj = cyg_ldr_open_library_fs( (cyg_uint8*)ptr ); + if ( e_obj == 0 ) + return 0; + rc = cyg_ldr_load_sections( e_obj ); + if ( rc != 0 ) + { + cyg_ldr_free_elf_object( e_obj ); + return 0; + } + + // Find the section index for the .shstrtab section. The names of the + // sections are held here, and are the only way to identify them. + p_shstrtab = (cyg_uint8*)cyg_ldr_section_address( e_obj, + e_obj->p_elfhdr->e_shstrndx ); + if ( p_shstrtab == 0 ) + { + cyg_ldr_free_elf_object( e_obj ); + return 0; + } + + // .symtab section and .strtab. We have to go through the section names + // to find where they are. + for ( i = 1; i < e_obj->p_elfhdr->e_shnum; i++ ) + { + // Now look for the index of .symtab. These are the symbols needed for + // the symbol retrieval as well as relocation. + if ( !strcmp( p_shstrtab + e_obj->p_sechdr[i].sh_name, + ELF_STRING_symtab ) ) + { + e_obj->hdrndx_symtab = i; + e_obj->sections[i] = cyg_ldr_load_elf_section( e_obj, i ); + if ( e_obj->sections[i] == 0 ) + { + cyg_ldr_free_elf_object( e_obj ); + return 0; + } + } + + // Load the table with the names of all the symbols. We need this + // to compare the name of external references symbols against the + // names in the in the CYG_HAL_TABLE provided by the user. + if ( !strcmp( p_shstrtab + e_obj->p_sechdr[i].sh_name, + ELF_STRING_strtab ) ) + { + e_obj->hdrndx_strtab = i; + e_obj->sections[i] = cyg_ldr_load_elf_section( e_obj, i ); + if ( e_obj->sections[i] == 0 ) + { + cyg_ldr_free_elf_object( e_obj ); + return 0; + } + } + } + + CYG_ASSERT( e_obj->hdrndx_symtab != 0, "No symtab index found" ); + CYG_ASSERT( e_obj->hdrndx_strtab != 0, "No strtab index found" ); + + // Now look for symbols in the COMMON area. The COMMON symbols are a + // special case, because the area they reside in must be sized up + // and allocated separately from the other sections, which appear in + // the sections header and can be read out of the library itself. + // Extra room in the 'sections' array has already been allocated to hold + // the pointer to the commons area. + common_size = cyg_ldr_find_common_size( e_obj ); + if ( common_size != 0 ) + { + cyg_uint32 com_shndx = e_obj->p_elfhdr->e_shnum; + cyg_int32 com_offset = 0; + + e_obj->sections[com_shndx] = (cyg_uint32*)cyg_ldr_malloc( common_size ); + CYG_ASSERT( e_obj->sections[com_shndx] != 0, + "Cannot malloc() the COMMONS" ); + + if ( e_obj->sections[com_shndx] == 0 ) + { + cyg_ldr_free_elf_object( e_obj ); + return 0; + } + + // Now find all the symbols in the SHN_COMMON area and make + // them point to the newly allocated COM area. + symtab_entries = e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_size / + e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_entsize; + p_symtab = (Elf32_Sym*)e_obj->sections[e_obj->hdrndx_symtab]; + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 + diag_printf( "Num Value Size Ndx Name\n" ); +#endif + for ( i = 1; i < symtab_entries; i++ ) + { +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 + cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address( e_obj, + e_obj->hdrndx_strtab ); +#endif + if ( p_symtab[i].st_shndx == SHN_COMMON ) + { + cyg_uint32 boundary = p_symtab[i].st_value - 1; + // Calculate the next byte boundary. + com_offset = ( com_offset + boundary ) & ~boundary; + p_symtab[i].st_shndx = com_shndx; + p_symtab[i].st_value = com_offset; + com_offset += p_symtab[i].st_size; + } + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 + diag_printf( "%03d %08X %04X %03d %s\n", + i, + p_symtab[i].st_value, + p_symtab[i].st_size, + p_symtab[i].st_shndx, + p_strtab + p_symtab[i].st_name ); +#endif + } + } + +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + cyg_ldr_print_section_data( e_obj ); +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 + cyg_ldr_print_symbol_names( e_obj ); +#endif +#endif + + for ( i = 1; i < e_obj->p_elfhdr->e_shnum; i++ ) + { + // Find all the '.rel' or '.rela' sections and relocate them. + if ( ( e_obj->p_sechdr[i].sh_type == SHT_REL ) || + ( e_obj->p_sechdr[i].sh_type == SHT_RELA ) ) + { + // Load and relocate the section. + rc = cyg_ldr_relocate_section( e_obj, i ); + if ( rc < 0 ) + { +#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 + ELFDEBUG( "Relocation unsuccessful\n" ); +#endif + cyg_ldr_free_elf_object( e_obj ); + return 0; + } + } + } + + // Synch up the caches before calling any function in the library. + cyg_ldr_flush_cache(); + + // Run the library initialization code. + fn = cyg_ldr_find_symbol( e_obj, "library_open" ); + if ( fn != 0 ) + fn(); + return ((void*)e_obj); +} + +cyg_uint8 +*cyg_ldr_error( void ) +{ + cyg_uint8* p = cyg_ldr_last_error; + cyg_ldr_last_error = NULL; + return p; +} + +void cyg_ldr_close_library( void* handle ) +{ + void (*fn)(void); + + PELF_OBJECT p = (PELF_OBJECT)handle; + fn = cyg_ldr_find_symbol( p, "library_close" ); + if ( fn != 0 ) + fn(); + + cyg_ldr_free_elf_object( p ); + p = 0; +} +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/src/relocate_ppc.c @@ -0,0 +1,119 @@ +/* ================================================================= + * + * relocate_ppc.c + * + * Relocation types for the PowerPC processor. + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#include <cyg/infra/diag.h> // For diagnostic printing. +#include <pkgconf/io_fileio.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_io.h> + +#include <pkgconf/objloader.h> +#include <cyg/objloader/elf.h> +#include <cyg/objloader/objelf.h> + +#ifdef CYGPKG_HAL_POWERPC +void +cyg_ldr_flush_cache( void ) +{ + HAL_DCACHE_SYNC(); + HAL_ICACHE_SYNC(); +} + +// in: +// +// sym_type Type of relocation to apply, +// mem Address in memory to modify (relocate). +// sym_value +cyg_int32 +cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value ) +{ + cyg_int32 rel_offset, i; + + // PPC uses rela, so we have to add the addend. + switch( sym_type ) + { + case R_PPC_ADDR16_HA: + HAL_WRITE_UINT16( mem, _ha_( sym_value ) ); + return 0; + case R_PPC_ADDR16_HI: + HAL_WRITE_UINT16( mem, _hi_( sym_value ) ); + return 0; + case R_PPC_ADDR16_LO: + HAL_WRITE_UINT16( mem, _lo_( sym_value ) ); + return 0; + case R_PPC_REL24: + // Now it is time to seek the destination address of the call. + // We need to do something in case the user jumps more than 16MB. + rel_offset = ( sym_value - mem ) & 0x03FFFFFC; + HAL_READ_UINT32( mem, i ); + i &= 0xFC000003; + HAL_WRITE_UINT32( mem, rel_offset | i ); + return 0; + case R_PPC_REL32: + HAL_WRITE_UINT32( mem, ( sym_value - mem ) ); + return 0; + case R_PPC_ADDR32: + HAL_WRITE_UINT32( mem, sym_value ); + return 0; + default: + ELFDEBUG( "FIXME: Unknown relocation value!!!\n" ); + return -1; + } +} +#endif // CYGPKG_HAL_POWERPC + +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/tests/library/hello.c @@ -0,0 +1,128 @@ +/* ================================================================= + * + * hello.c + * + * Sample library to test the object loader + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#include <cyg/kernel/kapi.h> // Kernel API. +#include <cyg/infra/diag.h> // For diagnostic printing. + +cyg_sem_t sem_signal_thread; +int thread_a_count; + +void weak_function( void ) CYGBLD_ATTRIB_WEAK; +void weak_function( void ) +{ + // Store the data value passed in for this thread. + diag_printf( "This is the library function\n" ); +} + +void library_open( void ) +{ + // Initialize the count for thread a. + thread_a_count = 0; + + // Initialize the semaphore with a count of zero, + // prior to creating the threads. + cyg_semaphore_init( &sem_signal_thread, 0 ); + diag_printf( "Library initialized...\n" ); +} + +void library_close( void ) +{ + diag_printf( "Ciao...\n" ); +} + +void print_message( void ) +{ + diag_printf( "Printing a silly message...\n" ); +} + +// Thread A - signals thread B via semaphore. +void thread_a( cyg_addrword_t data ) +{ + // Store the data value passed in for this thread. + int msg = (int)data; + + while( 1 ) + { + // Increment the thread a count. + thread_a_count++; + + + // Send out a message to the diagnostic port. + diag_printf( "Thread A, count: %d message: %d\n", thread_a_count, msg ); + + // Delay for 1 second. + cyg_thread_delay( 100 ); + + // Signal thread B using the semaphore. + cyg_semaphore_post( &sem_signal_thread ); + } +} + +// Thread B - waits for semaphore signal from thread A. +void thread_b( cyg_addrword_t data ) +{ + // Store the data value passed in for this thread. + int msg = (int)data; + + while( 1 ) + { + + // Signal thread B using the semaphore. + cyg_semaphore_wait( &sem_signal_thread ); + + // Send out a message to the diagnostic port. + diag_printf( "Thread B, message: %d\n", msg ); + } +} +
new file mode 100644 --- /dev/null +++ b/packages/services/objloader/current/tests/test_mods.c @@ -0,0 +1,207 @@ +/* ================================================================= + * + * test_mods.c + * + * Test program for the object loader. + * + * ================================================================= + * ####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating + * System. + * Copyright (C) 2005 eCosCentric Ltd. + * + * eCos is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 or (at your option) + * any later version. + * + * eCos is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCos; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or + * use macros or inline functions from this file, or you compile this + * file and link it with other works to produce a work based on this + * file, this file does not by itself cause the resulting work to be + * covered by the GNU General Public License. However the source code + * for this file must still be made available in accordance with + * section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work + * based on this file might be covered by the GNU General Public + * License. + * + * ------------------------------------------- + * ####ECOSGPLCOPYRIGHTEND#### + * ================================================================= + * #####DESCRIPTIONBEGIN#### + * + * Author(s): atonizzo@lycos.com + * Date: 2005-05-13 + * Purpose: + * Description: + * + * ####DESCRIPTIONEND#### + * + * ================================================================= + */ + +#include <cyg/kernel/kapi.h> // Kernel API. +#include <cyg/infra/diag.h> // For diagnostic printing. +#include <pkgconf/io_fileio.h> + +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <stdio.h> + +#include <cyg/fileio/fileio.h> +#include <cyg/objloader/elf.h> +#include <cyg/objloader/objelf.h> + +#define THREAD_STACK_SIZE 8192 +#define THREAD_PRIORITY 12 + +cyg_uint8 thread_a_stack[THREAD_STACK_SIZE] __attribute__((__aligned__ (16))); +cyg_uint8 thread_b_stack[THREAD_STACK_SIZE] __attribute__((__aligned__ (16))); + +cyg_thread thread_a_obj; +cyg_thread thread_b_obj; +cyg_handle_t thread_a_hdl; +cyg_handle_t thread_b_hdl; + +#define SHOW_RESULT( _fn, _res ) \ +diag_printf("<FAIL>: " #_fn "() returned %d %s\n", _res, _res<0?strerror(errno):""); + +void weak_function( void ) +{ + // Store the data value passed in for this thread. + diag_printf( "This is the application function\n" ); +} + +void (*thread_a)( cyg_addrword_t ); +void (*thread_b)( cyg_addrword_t ); + +// This is the main starting point for our example application. +void cyg_user_start( void ) +{ + int err; + void* lib_handle; + void (*fn)( void ); + + // It wouldn't be much of a basic example if some + // kind of hello message wasn't output. + diag_printf( "Hello eCos World!!!\n\n" ); + + err = mount( "/dev/disk0/1", "/", "fatfs" ); + if( err < 0 ) + SHOW_RESULT( mount, err ); + + err = chdir( "/" ); + if( err < 0 ) + SHOW_RESULT( chdir, err ); + + lib_handle = cyg_ldr_open_library( (CYG_ADDRWORD)"/hello.o", 0 ); +// cyg_ldr_print_symbol_names( lib_handle ); +// cyg_ldr_print_rel_names( lib_handle ); + fn = cyg_ldr_find_symbol( lib_handle, "print_message" ); + fn(); + fn = cyg_ldr_find_symbol( lib_handle, "weak_function" ); + fn(); + + thread_a = cyg_ldr_find_symbol( lib_handle, "thread_a" ); + thread_b = cyg_ldr_find_symbol( lib_handle, "thread_b" ); + + // Create our two threads. + cyg_thread_create( THREAD_PRIORITY, + thread_a, + (cyg_addrword_t) 75, + "Thread A", + (void *)thread_a_stack, + THREAD_STACK_SIZE, + &thread_a_hdl, + &thread_a_obj ); + + cyg_thread_create( THREAD_PRIORITY + 1, + thread_b, + (cyg_addrword_t) 68, + "Thread B", + (void *)thread_b_stack, + THREAD_STACK_SIZE, + &thread_b_hdl, + &thread_b_obj ); + + // Resume the threads so they start when the scheduler begins. + cyg_thread_resume( thread_a_hdl ); + cyg_thread_resume( thread_b_hdl ); +} + +// ----------------------------------------------------------------------------- +// External symbols. +// ----------------------------------------------------------------------------- + +// eCos semaphores +CYG_LDR_TABLE_ENTRY( cyg_thread_delay_entry, + "cyg_thread_delay", + cyg_thread_delay ); +CYG_LDR_TABLE_ENTRY( cyg_semaphore_wait_entry, + "cyg_semaphore_wait", + cyg_semaphore_wait ); +CYG_LDR_TABLE_ENTRY( cyg_semaphore_init_entry, + "cyg_semaphore_init", + cyg_semaphore_init ); +CYG_LDR_TABLE_ENTRY( cyg_semaphore_post_entry, + "cyg_semaphore_post", + cyg_semaphore_post ); + +// eCos mailboxes +CYG_LDR_TABLE_ENTRY( cyg_mbox_put_entry, "cyg_mbox_put", cyg_mbox_put ); + +// eCos Flags +CYG_LDR_TABLE_ENTRY( cyg_flag_poll_entry, "cyg_flag_poll", cyg_flag_poll ); +CYG_LDR_TABLE_ENTRY( cyg_flag_setbits_entry, + "cyg_flag_setbits", + cyg_flag_setbits ); + +// eCos misc +CYG_LDR_TABLE_ENTRY( hal_delay_us_entry, "hal_delay_us", hal_delay_us ); +CYG_LDR_TABLE_ENTRY( cyg_assert_msg_entry, "cyg_assert_msg", cyg_assert_msg ); +CYG_LDR_TABLE_ENTRY( cyg_assert_fail_entry, + "cyg_assert_fail", + cyg_assert_fail ); + +// memory +CYG_LDR_TABLE_ENTRY( memcpy_entry, "memcpy", memcpy ); +CYG_LDR_TABLE_ENTRY( memset_entry, "memset", memset ); +CYG_LDR_TABLE_ENTRY( memcmp_entry, "memcmp", memcmp ); +CYG_LDR_TABLE_ENTRY( malloc_entry, "malloc", malloc ); +CYG_LDR_TABLE_ENTRY( free_entry, "free", free ); + +// Strings +CYG_LDR_TABLE_ENTRY( strcpy_entry, "strcpy", strcpy ); +CYG_LDR_TABLE_ENTRY( strcat_entry, "strcat", strcat ); +CYG_LDR_TABLE_ENTRY( sprintf_entry, "sprintf", sprintf ); +CYG_LDR_TABLE_ENTRY( strlen_entry, "strlen", strlen ); +CYG_LDR_TABLE_ENTRY( strcmp_entry, "strcmp", strcmp ); +CYG_LDR_TABLE_ENTRY( strncmp_entry, "strncmp", strncmp ); + +// files +CYG_LDR_TABLE_ENTRY( fopen_entry, "fopen", fopen ); +CYG_LDR_TABLE_ENTRY( fread_entry, "fread", fread ); +CYG_LDR_TABLE_ENTRY( fclose_entry, "fclose", fclose ); +CYG_LDR_TABLE_ENTRY( fseek_entry, "fseek", fseek ); +CYG_LDR_TABLE_ENTRY( stat_entry, "stat", stat ); + +// Diagnostic printout +CYG_LDR_TABLE_ENTRY( diag_printf_entry, "diag_printf", diag_printf ); + +CYG_LDR_TABLE_ENTRY( weak_function_entry, "weak_function", weak_function );
