+2005-08-19 Dave Brolley <brolley@redhat.com>
+
+ * Contribute the following changes:
+
+ 2005-07-13 Dave Brolley <brolley@redhat.com>
+
+ * compLoader.cxx (generic_loader): Inherit virtually from
+ fixed_attribute_map_component. Inherit from no_relation_component.
+
+ 2005-06-06 Dave Brolley <brolley@redhat.com>
+
+ * elfload.c (readElfFile): Return and empty symbol table if none found.
+
+ * compLoader.cxx: Add using cleause for
+ sidutil::configurable_component.
+ (generic_loader): fixed_pin_map_component and configurable_component
+ inherited virtually.
+ (configure): New virtual override in generic_loader.
+ (check_function_pin_handler): Return the empty string if no function
+ is associated with the given address.
+ * sw-load-elf.xml: Add description of new interfaces.
+ * sw-load-elf.txt: Regenerated.
+
+ 2005-05-29 Dave Brolley <brolley@redhat.com>
+
+ * elfload.h (StringTable, Symbol): New struct types.
+ (readElfFile): New takes symbol_table argument.
+ (SHT_SYMTAB, SHT_STRTAB, ELF32_ST_TYPE, STT_FUNC): New macros.
+ * elfload.c (stringTables,stringTableCount,stringTableNum): New
+ static variables.
+ (newStringTable): New static function.
+ (symbolTable,symbolCount,symbolNum): New static variables.
+ (newSymbol): New static function.
+ (readElfFile): New takes symbol_table argument. Build string tables and
+ symbol table while reading the input file.
+ * compLoader.cxx (elf_loader): New constructor.
+ (load_it): Obtain symmol_table from readElfFile.
+ (check_function_pin,symbol_table,current_function): New members
+ of elf_loader.
+ (check_function_pin_handler): New method of elf_loader.
+
2005-06-03 Jim Blandy <jimb@redhat.com>
* Makefile.am (LIBIBERTY): Link against the libiberty.a from
// compLoader.cxx - object file loader component. -*- C++ -*-
-// Copyright (C) 1999, 2000, 2003, 2004 Red Hat.
+// Copyright (C) 1999, 2000, 2003, 2004, 2005 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
using sidutil::fixed_pin_map_component;
using sidutil::fixed_accessor_map_component;
using sidutil::no_relation_component;
+using sidutil::configurable_component;
using sidutil::output_pin;
using sidutil::callback_pin;
using sidutil::string2stream;
class generic_loader: public virtual component,
protected fixed_bus_map_component,
- protected fixed_attribute_map_component,
- protected fixed_pin_map_component,
+ protected virtual fixed_attribute_map_component,
+ protected virtual fixed_pin_map_component,
protected fixed_accessor_map_component,
- protected no_relation_component
+ protected no_relation_component,
+ protected virtual configurable_component
{
private:
callback_pin<generic_loader> doit_pin;
sid::component::status restore_state(const string& state)
{ return parse_attribute(state, *this); }
+ virtual void configure (const string &config);
+
public:
generic_loader():
doit_pin(this, & generic_loader::load_it),
};
+void
+generic_loader::configure (const string &config)
+{
+ // Call up to the base class first
+ configurable_component::configure (config);
+
+ // Now handle relevent configuration for us.
+ if (config.size () < 12)
+ return;
+ if (config.substr (0, 8) == "verbose=")
+ {
+ verbose_p = (config.substr (8) == "true");
+ return;
+ }
+}
+
ostream&
operator << (ostream& out, const generic_loader& it)
{
class elf_loader: public generic_loader
{
+public:
+ elf_loader ()
+ : generic_loader (),
+ symbol_table (0),
+ current_function (""),
+ check_function_pin (this, &elf_loader::check_function_pin_handler)
+ {
+ add_pin ("function?", &check_function_pin);
+ add_attribute ("current-function", & current_function);
+ }
+ ~elf_loader () throw () {}
+
+private:
// static pointer to active instance (XXX: concurrency?)
static elf_loader* freeloader;
const struct TextSection *section_table;
int success_p = readElfFile(& elf_loader::load_function,
& entry_point, & little_endian_p,
- & eflags, & section_table);
+ & eflags, & section_table, & symbol_table);
probe_upstream.set_section_table (section_table);
elf_loader::freeloader = 0;
delete this->file;
this->file = 0;
}
+
+protected:
+ callback_pin<elf_loader> check_function_pin;
+ void check_function_pin_handler (host_int_4 addr);
+
+ const struct Symbol *symbol_table;
+ string current_function;
};
// static variable
return bytes;
}
+void
+elf_loader::check_function_pin_handler (host_int_4 addr)
+{
+ // Find the function corresponding to the given address in the symbol
+ // table, if any, and set current_function to that name. If no function is
+ // found, set current_function to a string representing the address.
+ if (symbol_table)
+ {
+ unsigned closest = 0;
+ host_int_8 min_difference = ~(host_int_8)0;
+ unsigned ix;
+ for (ix = 0; symbol_table[ix].name; ++ix)
+ {
+ // Don't consider unnamed symbols.
+ if (! symbol_table[ix].name[0])
+ continue;
+ host_int_8 sym_addr = symbol_table[ix].addr;
+ host_int_8 sym_size = symbol_table[ix].size;
+ if (addr == sym_addr)
+ break;
+ if (addr > sym_addr && addr < (sym_addr + sym_size))
+ break;
+ if (addr - sym_addr < min_difference)
+ {
+ min_difference = addr - sym_addr;
+ closest = ix;
+ }
+ }
+ if (symbol_table[ix].name)
+ {
+ current_function = symbol_table[ix].name;
+ return;
+ }
+ if (closest != 0)
+ {
+ current_function = symbol_table[closest].name;
+ return;
+ }
+ }
+ current_function = "";
+}
+
// ----------------------------------------------------------------------------
static
/* Simple ELF loader
*
- * Copyright (c) 1998, 2002, 2004 Red Hat
+ * Copyright (c) 1998, 2002, 2004, 2005 Red Hat
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
{
int i;
- // Not a text section address if there is no table.
+ /* Not a text section address if there is no table. */
if (! section_table)
return 0;
return 0;
}
+/* A new string table table is created for each loader in the system. */
+static struct StringTable *stringTables;
+static int stringTableCount;
+static int stringTableNum;
+
+static void
+newStringTable (int index)
+{
+ if (index >= stringTableNum)
+ {
+ stringTableNum = index + 10;
+ stringTables = xrealloc (stringTables, stringTableNum * sizeof (*stringTables));
+ }
+}
+
+/* A new symbol table is created for each loader in the system. */
+static struct Symbol *symbolTable;
+static int symbolCount;
+static int symbolNum;
+
+static void
+newSymbol (int index)
+{
+ if (index >= symbolNum)
+ {
+ symbolNum = index + 10;
+ symbolTable = xrealloc (symbolTable, symbolNum * sizeof (*symbolTable));
+ }
+}
+
/* Read in an ELF file, using FUNC to read data from the stream.
The result is a boolean indicating success.
int
readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian,
- unsigned* e_flags, const struct TextSection **section_table)
+ unsigned* e_flags, const struct TextSection **section_table,
+ const struct Symbol **symbol_table)
{
unsigned char fileHeader [64];
unsigned char psymHdr [56];
unsigned char secHdr [64];
+ unsigned char symTabEntry [16];
unsigned long long psymOffset;
int psymSize;
int psymNum;
+ unsigned long long symbolTableOffset;
+ unsigned long long symbolTableSize;
+ unsigned long long symbolTableStringTableIx;
int eFlags;
unsigned long long secOffset;
int secSize;
/* 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. */
- textSections = 0;
- textSectionNum = 0;
- textSectionCount = 0;
- newTextSection (textSectionCount);
+ code, data, symbols and strings. */
if (sixtyfourbit)
{
secOffset = fetchQuad (fileHeader+40, littleEndian);
secSize = fetchShort (fileHeader+46, littleEndian);
secNum = fetchShort (fileHeader+48, littleEndian);
}
+ textSections = 0;
+ textSectionNum = 0;
+ textSectionCount = 0;
+ stringTables = 0;
+ stringTableNum = 0;
+ stringTableCount = 0;
+ newTextSection (textSectionCount);
for (x = 0; x < secNum; x++)
{
if (func (0, secHdr, secOffset, secSize, 0) != secSize)
}
else
{
- if (fetchWord(secHdr+8, littleEndian) & SHF_EXECINSTR)
+ unsigned flags = fetchWord(secHdr+8, littleEndian);
+ if (flags & SHF_EXECINSTR)
{
textSections[textSectionCount].lbound =
fetchWord(secHdr+12, littleEndian);
textSectionCount++;
newTextSection (textSectionCount);
}
+ else if (fetchWord(secHdr+4, littleEndian) == SHT_STRTAB)
+ {
+ unsigned offset = fetchWord(secHdr+16, littleEndian);
+ unsigned size = fetchWord(secHdr+20, littleEndian);
+ char *strings = xmalloc (size);
+ newStringTable (stringTableCount);
+ stringTables[stringTableCount].ix = x;
+ stringTables[stringTableCount].strings = strings;
+ if (func (0, strings, offset, size, 0) != size)
+ return 0;
+ ++stringTableCount;
+ }
+ else if (fetchWord(secHdr+4, littleEndian) == SHT_SYMTAB)
+ {
+ symbolTableOffset = fetchWord(secHdr+16, littleEndian);
+ symbolTableSize = fetchWord(secHdr+20, littleEndian);
+ symbolTableStringTableIx = fetchWord(secHdr+24, littleEndian);
+ }
}
secOffset += secSize;
}
textSections[textSectionCount].lbound = 0;
textSections[textSectionCount].hbound = 0;
+ /* Can't look for functions in the symbol table until all the sections have been
+ examined, since the string table for the symbol table may follow the symbol
+ table itself. Identify the correct string table first. */
+ const char *strings = 0;
+ for (x = 0; x < stringTableCount; ++x)
+ {
+ if (stringTables[x].ix == symbolTableStringTableIx)
+ strings = stringTables[x].strings;
+ }
+
+ /* Now look for functions and record their addresses and lengths. */
+ symbolTable = 0;
+ symbolCount = 0;
+ symbolNum = 0;
+ newSymbol (symbolCount);
+ if (strings)
+ {
+ for (x = 0; x < symbolTableSize; x += sizeof (symTabEntry))
+ {
+ if (func (0, symTabEntry, symbolTableOffset + x, sizeof (symTabEntry), 0) != sizeof (symTabEntry))
+ return 0;
+ // TODO: Save only symbols representing functions
+ // PROBLEM: Some don't have the STT_FUNC flag set
+ symbolTable[symbolCount].name = strings + fetchWord(symTabEntry+0, littleEndian);
+ symbolTable[symbolCount].addr = fetchWord(symTabEntry+4, littleEndian);
+ symbolTable[symbolCount].size = fetchWord(symTabEntry+8, littleEndian);
+#if 0
+ printf ("found symbol %s at 0x%Lx for 0x%Lx\n",
+ symbolTable[symbolCount].name,
+ symbolTable[symbolCount].addr,
+ symbolTable[symbolCount].size);
+#endif
+ symbolCount++;
+ newSymbol (symbolCount);
+ }
+ }
+ // Terminate the symbol table.
+ symbolTable[symbolCount].name = 0;
+
*entry_point = entryPoint;
*little_endian = littleEndian;
*section_table = textSections;
+ *symbol_table = symbolTable;
*e_flags = eFlags;
return 1;
/* Header for simple ELF loader
*
- * Copyright (c) 1998, 2004 Red Hat
+ * Copyright (c) 1998, 2004, 2005 Red Hat
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
unsigned long long hbound;
};
+struct StringTable
+{
+ unsigned ix;
+ const char *strings;
+};
+
+struct Symbol
+{
+ const char *name;
+ unsigned long long addr;
+ unsigned long long size;
+};
+
/*
PFLOAD represents a function that will read file data.
DEST or DEST2 is used as the destination address to be written with the
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*, unsigned*, const struct TextSection **);
+extern int readElfFile(PFLOAD func, unsigned*, int*, unsigned*, const struct TextSection **, const struct Symbol **);
#define EI_CLASS 4
#define ELFCLASS64 2 /* 64 bit */
/* ELF section header flags */
#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
+/* ELF section header types */
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+
+/* ELF Symbol Table fields */
+#define ELF32_ST_TYPE(i) ((i)&0xf)
+#define STT_FUNC 2
+
#endif
| | encourages this component to |
| | provide informative messages |
| | to cout during loading. |
+ | | |
+ | | When the configure! is set, |
+ | | the new value is interpreted |
+ | | as a configuration spec. The |
+ | | spec is a colon-separated list |
+ | | of items, each of which is |
+ | | passed in turn to the |
+ | | 'configure' method for |
+ | | interpretation and possible |
+ | | action. |
|----------------+--------------------------------|
| loading | When the load! pin is driven, |
| | this component will attempt to |
Component: sw-load-elf
- +-------------------------------------------------------------+
- | pins |
- |-------------------------------------------------------------|
- | name | direction | legalvalues | behaviors |
- |-----------------------+-----------+-------------+-----------|
- |load! |in |any |loading |
- |-----------------------+-----------+-------------+-----------|
- |start-pc-set |out |any |loading |
- |-----------------------+-----------+-------------+-----------|
- |endian-set |out |0/1/2 |loading |
- |-----------------------+-----------+-------------+-----------|
- |error |out |any |loading |
- |-----------------------+-----------+-------------+-----------|
- |write-to-code-address |out |any address |error |
- | | | |checking |
- |-----------------------+-----------+-------------+-----------|
- |probe |in |any address |error |
- | | | |checking |
- +-------------------------------------------------------------+
+ +-----------------------------------------------------------------+
+ | pins |
+ |-----------------------------------------------------------------|
+ | name | direction | legalvalues | behaviors |
+ |-----------------------+-----------+-------------+---------------|
+ |function-address? |in |address |configuration |
+ |-----------------------+-----------+-------------+---------------|
+ |load! |in |any |loading |
+ |-----------------------+-----------+-------------+---------------|
+ |start-pc-set |out |any |loading |
+ |-----------------------+-----------+-------------+---------------|
+ |endian-set |out |0/1/2 |loading |
+ |-----------------------+-----------+-------------+---------------|
+ |error |out |any |loading |
+ |-----------------------+-----------+-------------+---------------|
+ |write-to-code-address |out |any address |error checking |
+ |-----------------------+-----------+-------------+---------------|
+ |probe |in |any address |error checking |
+ +-----------------------------------------------------------------+
+-----------------------------------------------------+
| buses |
| | |name | | ||
|----------------+----------+--------+-------------+---------------||
|verbose? |setting |1/0 |0 |configuration ||
+ |----------------+----------+--------+-------------+---------------||
+ |configure! |setting |string |- |configuration ||
+-------------------------------------------------------------------+
+-------------------------------------------------+
<defcomplib lib="libloader.la" dlsym="loader_component_library">
<defcomponent name="sw-load-elf" type="concrete">
+ <!-- relationships -->
+ <defrelationship name="dynamic-configurator" behaviors="configuration" />
+
+ <!-- pins -->
+ <defpin name="function-address?" direction="in" legalvalues="address" behaviors="configuration" />
<defpin name="load!" direction="in" legalvalues="any" behaviors="loading"/>
<defpin name="start-pc-set" direction="out" legalvalues="any" behaviors="loading"/>
<defpin name="endian-set" direction="out" legalvalues="0/1/2" behaviors="loading"/>
<defattribute name="state-snapshot" legalvalues="opaque string" behaviors="save/restore"/>
<defattribute name="file" category="setting" legalvalues="file name" defaultvalue='"/dev/null"' behaviors="configuration"/>
<defattribute name="verbose?" category="setting" legalvalues="1/0" defaultvalue="0" behaviors="configuration"/>
+ <defattribute name="configure!" category="setting" legalvalues="string" behaviors="configuration" />
<defbus name="probe-upstream" accesses="read/write" behaviors="error checking"/>
The "verbose?" attribute, when set, encourages this component to provide
informative messages to cout during loading.
</p>
+
+ <p>When the <attribute>configure!</attribute> is set, the new value is interpreted
+ as a configuration spec. The spec is a colon-separated list of items, each of
+ which is passed in turn to the 'configure' method for interpretation and possible
+ action.</p>
+
</behavior>
<behavior name="loading">