Index: sid/component/loader/Makefile.am =================================================================== RCS file: /cvs/src/src/sid/component/loader/Makefile.am,v retrieving revision 1.2 diff -c -p -r1.2 Makefile.am *** sid/component/loader/Makefile.am 4 Aug 2001 11:07:50 -0000 1.2 --- sid/component/loader/Makefile.am 12 Feb 2004 20:14:46 -0000 *************** *** 2,7 **** --- 2,9 ---- AUTOMAKE_OPTIONS = foreign + LIBIBERTY = -L../../../libiberty -liberty + pkglib_LTLIBRARIES = libloader.la pkgdata_DATA = sw-load-elf.txt *************** pkgdata_DATA = sw-load-elf.txt *** 9,14 **** --- 11,17 ---- INCLUDES = -I. -I../../include -I$(srcdir)/../../include libloader_la_SOURCES = compLoader.cxx elfload.c libloader_la_LDFLAGS = -module -no-undefined + libloader_la_LIBADD = $(LIBIBERTY) html_stylesheet=$(srcdir)/../component_html.xsl include $(srcdir)/../../config/Makefile.docs Index: sid/component/loader/compLoader.cxx =================================================================== RCS file: /cvs/src/src/sid/component/loader/compLoader.cxx,v retrieving revision 1.6 diff -c -p -r1.6 compLoader.cxx *** sid/component/loader/compLoader.cxx 21 Oct 2003 21:30:44 -0000 1.6 --- sid/component/loader/compLoader.cxx 12 Feb 2004 20:14:49 -0000 *************** *** 1,6 **** // compLoader.cxx - object file loader component. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2003 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,6 ---- // compLoader.cxx - object file loader component. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2003, 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** using sid::bus; *** 41,46 **** --- 41,47 ---- using sid::host_int_1; using sid::little_int_1; using sid::host_int_4; + using sid::host_int_8; using sid::component_library; using sid::COMPONENT_LIBRARY_MAGIC; *************** using sidutil::std_error_string; *** 62,69 **** // A bus for allowing the loader to perform random checks against reads and writes // to memory. For example writing to a code area. Default implementation - extern "C" int textSegmentAddress(int); - class loader_probe_bus: public sidutil::passthrough_bus { public: --- 63,68 ---- *************** class loader_probe_bus: public sidutil:: *** 75,87 **** } ~loader_probe_bus() throw() {} // Some macros to make manufacturing of the cartesian-product // calls simpler. #define SID_GB_WRITE(dtype) \ sid::bus::status write(sid::host_int_4 addr, dtype data) throw ()\ { if (LIKELY(*target)) \ { \ ! if (write_to_code_address_pin && textSegmentAddress (addr)) \ write_to_code_address_pin->drive (addr); \ return (*target)->write(addr, data); \ } \ --- 74,88 ---- } ~loader_probe_bus() throw() {} + void set_section_table (const struct TextSection *s) { section_table = s; } + // Some macros to make manufacturing of the cartesian-product // calls simpler. #define SID_GB_WRITE(dtype) \ sid::bus::status write(sid::host_int_4 addr, dtype data) throw ()\ { if (LIKELY(*target)) \ { \ ! if (write_to_code_address_pin && textSectionAddress (addr, section_table)) \ write_to_code_address_pin->drive (addr); \ return (*target)->write(addr, data); \ } \ *************** class loader_probe_bus: public sidutil:: *** 100,105 **** --- 101,107 ---- #undef SID_GB_WRITE output_pin *write_to_code_address_pin; + const struct TextSection *section_table; }; class generic_loader: public virtual component, *************** class elf_loader: public generic_loader *** 246,253 **** elf_loader::freeloader = this; unsigned entry_point; int little_endian_p; int success_p = readElfFile(& elf_loader::load_function, ! & entry_point, & little_endian_p); elf_loader::freeloader = 0; if (success_p) --- 248,258 ---- elf_loader::freeloader = this; unsigned entry_point; int little_endian_p; + const struct TextSection *section_table; int success_p = readElfFile(& elf_loader::load_function, ! & entry_point, & little_endian_p, ! & section_table); ! probe_upstream.set_section_table (section_table); elf_loader::freeloader = 0; if (success_p) Index: sid/component/loader/elfload.c =================================================================== RCS file: /cvs/src/src/sid/component/loader/elfload.c,v retrieving revision 1.5 diff -c -p -r1.5 elfload.c *** sid/component/loader/elfload.c 21 Oct 2003 21:30:44 -0000 1.5 --- sid/component/loader/elfload.c 12 Feb 2004 20:14:49 -0000 *************** *** 1,6 **** /* Simple ELF loader * ! * Copyright (c) 1998, 2002 Red Hat * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided --- 1,6 ---- /* Simple ELF loader * ! * Copyright (c) 1998, 2002, 2004 Red Hat * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided *************** *** 14,51 **** */ #include #include ! ! unsigned char fileHeader [64]; ! unsigned char psymHdr[56]; #define PT_LOAD 1 ! struct LoadAreas { ! host_int_8 loadAddr; ! host_int_8 filesize; ! host_int_8 offset; int flags; int loaded; ! } loadAreas[100]; // XXX: limit on number of loadable sections ! static struct TextSegment { ! host_int_8 lbound; ! host_int_8 hbound; ! } textSegments[100]; ! static int textSegmentsCount = 0; ! enum {execute_flag = 1}; int ! textSegmentAddress (int address) { int i; ! for (i = 0; i < textSegmentsCount ; i++) { ! if (textSegments[i].lbound <= address ! && address <= textSegments[i].hbound) return 1; } return 0; --- 14,70 ---- */ #include #include ! #include "libiberty.h" #define PT_LOAD 1 ! /* The loadAreas table is reused by each loader. */ ! static struct LoadAreas { ! unsigned long long loadAddr; ! unsigned long long filesize; ! unsigned long long offset; int flags; int loaded; ! } *loadAreas = 0; ! static void ! newLoadArea (int index) { ! static loadAreaNum = 0; ! if (index >= loadAreaNum) ! { ! loadAreaNum = index + 10; ! loadAreas = xrealloc (loadAreas, loadAreaNum * sizeof (*loadAreas)); ! } ! } ! ! /* The section table is kept for the duration of the simulation. ! It is divided into sub tables, one for each loader in the system. */ ! static int textSectionCount = 0; ! static struct TextSection *textSections = 0; + static void + newTextSection (int index) + { + static textSectionNum = 0; + if (index >= textSectionNum) + { + textSectionNum = index + 10; + textSections = xrealloc (textSections, textSectionNum * sizeof (*textSections)); + } + } int ! textSectionAddress (unsigned long long address, const struct TextSection *section_table) { + /* The table begins with the given pointer and is terminated by an entry with + zeroes for both the high and low bounds. */ int i; ! for (i = 0; section_table[i].lbound != 0 || section_table[i].hbound != 0; i++) { ! if (section_table[i].lbound <= address ! && address <= section_table[i].hbound) return 1; } return 0; *************** textSegmentAddress (int address) *** 59,74 **** */ int ! readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian) { ! host_int_8 psymOffset; int psymSize; int psymNum; ! host_int_8 entryPoint = 0; ! int loadAreaCount = 0; int x; int littleEndian; int sixtyfourbit; /* This is relatively straightforward. We first read in the file header, find out how many sections there are, determine which ones are loadable --- 78,99 ---- */ int ! readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian, const struct TextSection **section_table) { ! unsigned char fileHeader [64]; ! unsigned char psymHdr [56]; ! unsigned char secHdr [64]; ! unsigned long long psymOffset; int psymSize; int psymNum; ! unsigned long long secOffset; ! int secSize; ! int secNum; ! unsigned long long entryPoint = 0; int x; int littleEndian; int sixtyfourbit; + int loadAreaCount = 0; /* This is relatively straightforward. We first read in the file header, find out how many sections there are, determine which ones are loadable *************** readElfFile (PFLOAD func, unsigned* entr *** 77,83 **** There is one major failing, tho--if the psym header isn't at the front of the file, and we're loading from a stream that we can't back up on, we will lose. */ ! if (func (NULL, fileHeader, 0, 64, 0) != 64) { return 0; } --- 102,108 ---- There is one major failing, tho--if the psym header isn't at the front of the file, and we're loading from a stream that we can't back up on, we will lose. */ ! if (func (0, fileHeader, 0, 64, 0) != 64) { return 0; } *************** readElfFile (PFLOAD func, unsigned* entr *** 108,121 **** } for (x = 0; x < psymNum; x++) { if (sixtyfourbit) { - if (func (NULL, psymHdr, psymOffset, 56, 0) != 56) - { - return 0; - } if (fetchWord (psymHdr, littleEndian) == PT_LOAD) { loadAreas[loadAreaCount].loadAddr = fetchQuad(psymHdr+24, littleEndian); loadAreas[loadAreaCount].offset = fetchQuad(psymHdr+8, littleEndian); --- 133,147 ---- } for (x = 0; x < psymNum; x++) { + if (func (0, psymHdr, psymOffset, psymSize, 0) != psymSize) + { + return 0; + } if (sixtyfourbit) { if (fetchWord (psymHdr, littleEndian) == PT_LOAD) { + newLoadArea (loadAreaCount); loadAreas[loadAreaCount].loadAddr = fetchQuad(psymHdr+24, littleEndian); loadAreas[loadAreaCount].offset = fetchQuad(psymHdr+8, littleEndian); *************** readElfFile (PFLOAD func, unsigned* entr *** 123,150 **** littleEndian); loadAreas[loadAreaCount].flags = fetchWord(psymHdr+4, littleEndian); loadAreas[loadAreaCount].loaded = 0; - - if (loadAreas[loadAreaCount].flags & execute_flag) - { - textSegments[textSegmentsCount].lbound = - loadAreas[loadAreaCount].loadAddr; - textSegments[textSegmentsCount].hbound = - loadAreas[loadAreaCount].loadAddr - + loadAreas[loadAreaCount].filesize; - textSegmentsCount++; - } - loadAreaCount++; } } else { - if (func (NULL, psymHdr, psymOffset, 32, 0) != 32) - { - return 0; - } if (fetchWord (psymHdr, littleEndian) == PT_LOAD) { loadAreas[loadAreaCount].loadAddr = fetchWord(psymHdr+12, littleEndian); loadAreas[loadAreaCount].offset = fetchWord(psymHdr+4, littleEndian); --- 149,162 ---- littleEndian); loadAreas[loadAreaCount].flags = fetchWord(psymHdr+4, littleEndian); loadAreas[loadAreaCount].loaded = 0; loadAreaCount++; } } else { if (fetchWord (psymHdr, littleEndian) == PT_LOAD) { + newLoadArea (loadAreaCount); loadAreas[loadAreaCount].loadAddr = fetchWord(psymHdr+12, littleEndian); loadAreas[loadAreaCount].offset = fetchWord(psymHdr+4, littleEndian); *************** readElfFile (PFLOAD func, unsigned* entr *** 152,168 **** littleEndian); loadAreas[loadAreaCount].flags = fetchWord(psymHdr+24, littleEndian); loadAreas[loadAreaCount].loaded = 0; - - if (loadAreas[loadAreaCount].flags & execute_flag) - { - textSegments[textSegmentsCount].lbound = - loadAreas[loadAreaCount].loadAddr; - textSegments[textSegmentsCount].hbound = - loadAreas[loadAreaCount].loadAddr - + loadAreas[loadAreaCount].filesize; - textSegmentsCount++; - } - loadAreaCount++; } } --- 164,169 ---- *************** readElfFile (PFLOAD func, unsigned* entr *** 200,205 **** --- 201,262 ---- /* FIXME: If no program segment header, loop over sections instead. */ /* FIXME: admin part of program segment is loaded. */ + + /* Look in the section table in order to determine which sections contain + code and which contain data. */ + newTextSection (textSectionCount); + *section_table = textSections + textSectionCount; + if (sixtyfourbit) + { + secOffset = fetchQuad (fileHeader+40, littleEndian); + secSize = fetchShort (fileHeader+58, littleEndian); + secNum = fetchShort (fileHeader+60, littleEndian); + } + else + { + secOffset = fetchWord (fileHeader+32, littleEndian); + secSize = fetchShort (fileHeader+46, littleEndian); + secNum = fetchShort (fileHeader+48, littleEndian); + } + for (x = 0; x < secNum; x++) + { + if (func (0, secHdr, secOffset, secSize, 0) != secSize) + { + return 0; + } + if (sixtyfourbit) + { + if (fetchQuad(secHdr+8, littleEndian) & SHF_EXECINSTR) + { + textSections[textSectionCount].lbound = + fetchQuad(secHdr+24, littleEndian); + textSections[textSectionCount].hbound = + textSections[textSectionCount].lbound + + fetchQuad(secHdr+32, littleEndian) - 1; + textSectionCount++; + newTextSection (textSectionCount); + } + } + else + { + if (fetchWord(secHdr+8, littleEndian) & SHF_EXECINSTR) + { + textSections[textSectionCount].lbound = + fetchWord(secHdr+16, littleEndian); + textSections[textSectionCount].hbound = + textSections[textSectionCount].lbound + + fetchWord(secHdr+20, littleEndian) - 1; + textSectionCount++; + newTextSection (textSectionCount); + } + } + secOffset += secSize; + } + + /* Terminate this portion of the section table. */ + textSections[textSectionCount].lbound = 0; + textSections[textSectionCount].hbound = 0; + textSectionCount++; *entry_point = entryPoint; *little_endian = littleEndian; Index: sid/component/loader/elfload.h =================================================================== RCS file: /cvs/src/src/sid/component/loader/elfload.h,v retrieving revision 1.3 diff -c -p -r1.3 elfload.h *** sid/component/loader/elfload.h 21 Oct 2003 21:30:44 -0000 1.3 --- sid/component/loader/elfload.h 12 Feb 2004 20:14:49 -0000 *************** *** 1,6 **** /* Header for simple ELF loader * ! * Copyright (c) 1998 Red Hat * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided --- 1,6 ---- /* Header for simple ELF loader * ! * Copyright (c) 1998, 2004 Red Hat * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided *************** *** 18,31 **** #define BYTE(X,offset) (((X)[offset]) & 255) #define fetchShortLittle(addr) (BYTE((addr),1)*256+BYTE((addr),0)) #define fetchWordLittle(addr) (fetchShortLittle (addr) + fetchShortLittle((addr) + 2) * 65536) ! #define fetchQuadLittle(addr) (fetchWordLittle ((addr)) + ((host_int_8)fetchWordLittle((addr) + 4) << 32)) #define fetchShortBig(addr) (BYTE((addr),0)*256+BYTE((addr),1)) #define fetchWordBig(addr) (fetchShortBig (addr) * 65536 + fetchShortBig((addr) + 2)) ! #define fetchQuadBig(addr) (((host_int_8)fetchWordBig ((addr)) << 32) + fetchWordBig((addr) + 4)) #define fetchShort(ADDR,LITTLE) ((LITTLE) ? fetchShortLittle((ADDR)) : fetchShortBig((ADDR))) #define fetchWord(ADDR,LITTLE) ((LITTLE) ? fetchWordLittle((ADDR)) : fetchWordBig((ADDR))) #define fetchQuad(ADDR,LITTLE) ((LITTLE) ? fetchQuadLittle((ADDR)) : fetchQuadBig((ADDR))) /* PFLOAD represents a function that will read file data. DEST or DEST2 is used as the destination address to be written with the --- 18,37 ---- #define BYTE(X,offset) (((X)[offset]) & 255) #define fetchShortLittle(addr) (BYTE((addr),1)*256+BYTE((addr),0)) #define fetchWordLittle(addr) (fetchShortLittle (addr) + fetchShortLittle((addr) + 2) * 65536) ! #define fetchQuadLittle(addr) (fetchWordLittle ((addr)) + ((unsigned long long)fetchWordLittle((addr) + 4) << 32)) #define fetchShortBig(addr) (BYTE((addr),0)*256+BYTE((addr),1)) #define fetchWordBig(addr) (fetchShortBig (addr) * 65536 + fetchShortBig((addr) + 2)) ! #define fetchQuadBig(addr) (((unsigned long long)fetchWordBig ((addr)) << 32) + fetchWordBig((addr) + 4)) #define fetchShort(ADDR,LITTLE) ((LITTLE) ? fetchShortLittle((ADDR)) : fetchShortBig((ADDR))) #define fetchWord(ADDR,LITTLE) ((LITTLE) ? fetchWordLittle((ADDR)) : fetchWordBig((ADDR))) #define fetchQuad(ADDR,LITTLE) ((LITTLE) ? fetchQuadLittle((ADDR)) : fetchQuadBig((ADDR))) + struct TextSection + { + unsigned long long lbound; + unsigned long long hbound; + }; + /* PFLOAD represents a function that will read file data. DEST or DEST2 is used as the destination address to be written with the *************** *** 37,50 **** If OFFSET and AMOUNT are both negative, then the file should be closed (any remaining bytes are to be ignored). */ ! typedef unsigned long long host_int_8; /* XXX */ ! ! typedef int (*PFLOAD)(host_int_8 dest, char *dest2, host_int_8 offset, host_int_8 amount, int insn_space); /* Is address in the text segment? */ ! extern int textSegmentAddress(int); /* Load an ELF executable into memory. FUNC is used to actually read the file. */ ! extern int readElfFile(PFLOAD func, unsigned*, int*); #define EI_CLASS 4 #define ELFCLASS64 2 /* 64 bit */ --- 43,54 ---- If OFFSET and AMOUNT are both negative, then the file should be closed (any remaining bytes are to be ignored). */ ! typedef int (*PFLOAD)(unsigned long long dest, char *dest2, unsigned long long offset, unsigned long long amount, int insn_space); /* Is address in the text segment? */ ! extern int textSectionAddress(unsigned long long, const struct TextSection *); /* Load an ELF executable into memory. FUNC is used to actually read the file. */ ! extern int readElfFile(PFLOAD func, unsigned*, int*, const struct TextSection **); #define EI_CLASS 4 #define ELFCLASS64 2 /* 64 bit */ *************** extern int readElfFile(PFLOAD func, unsi *** 55,59 **** --- 59,66 ---- /* Elf program header flags */ #define PF_X 0x01 /* executable */ #define PF_R 0x04 /* readable */ + + /* ELF section header flags */ + #define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */ #endif