From fdb1fe685ab60de784b5f20413fe54cd70a01ff2 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 30 Oct 2014 17:55:18 +1100 Subject: linkers: Add base image symbol to ELF object file generation. This change adds support to the rtems-syms code to generate a suitable ELF object you can link to the base image kernel in the embed mode or you can load with the run-time load mode. The change fixes a bug in the framework where local ELF symbols were being placed in the external symbol table. The external symbol table has been removed and a global, weak and local set of tables is now provided as this is more aligned with the ELF format. --- linkers/rtems-syms.cpp | 144 ++++++++++++++++++++++-------------------- rtemstoolkit/rld-files.cpp | 38 ++++++++--- rtemstoolkit/rld-process.cpp | 13 ++-- rtemstoolkit/rld-resolver.cpp | 4 +- rtemstoolkit/rld-symbols.cpp | 71 ++++++++++++++++----- rtemstoolkit/rld-symbols.h | 55 +++++++++++++--- rtemstoolkit/rtems-utils.h | 4 +- 7 files changed, 215 insertions(+), 114 deletions(-) diff --git a/linkers/rtems-syms.cpp b/linkers/rtems-syms.cpp index 618c7bd..5d9f10a 100644 --- a/linkers/rtems-syms.cpp +++ b/linkers/rtems-syms.cpp @@ -55,49 +55,52 @@ static const char* c_header[] = { "/*", " * RTEMS Global Symbol Table", - " * Automatically generated so no point in hacking on it.", + " * Automatically generated. Do not edit..", " */", "", - "#if __bfin__ || __h8300__ || __v850__", - " extern unsigned char _rtems_rtl_base_globals[];", - " extern unsigned int _rtems_rtl_base_globals_size;", - "#else", - " extern unsigned char __rtems_rtl_base_globals[];", - " extern unsigned int __rtems_rtl_base_globals_size;", - "#endif", + "extern const unsigned char rtems__rtl_base_globals[];", + "extern const unsigned int rtems__rtl_base_globals_size;", + "", + "void rtems_rtl_base_sym_global_add (const unsigned char* , unsigned int );", + "", + "asm(\".section \\\".rodata\\\"\");", "", "asm(\" .align 4\");", - "asm(\"__rtems_rtl_base_globals:\");", + "asm(\" .local rtems__rtl_base_globals\");", + "asm(\"rtems__rtl_base_globals:\");", + "#if __mips__", + " asm(\" .align 0\");", + "#else", + " asm(\" .balign 1\");", + "#endif", 0 }; static const char* c_trailer[] = { "asm(\" .byte 0\");", - "#if __mips__", - " asm(\" .align 0\");", - "#else", - " asm(\" .balign 1\");", - "#endif", - "asm(\" .ascii \\\"\\xde\\xad\\xbe\\xef\\\"\");", + "asm(\" .ascii \\\"\\xde\\xad\\xbe\\xef\\\"\");", + "asm(\" .type rtems__rtl_base_globals, #object\");", + "asm(\" .size rtems__rtl_base_globals, . - rtems__rtl_base_globals\");", + "", + "/*", + " * Symbol table size.", + " */", "asm(\" .align 4\");", - "asm(\"__rtems_rtl_base_globals_size:\");", - "asm(\" .long __rtems_rtl_base_globals_size - __rtems_rtl_base_globals\");", + "asm(\" .local rtems__rtl_base_globals_size\");", + "asm(\" .type rtems__rtl_base_globals_size, #object\");", + "asm(\" .size rtems__rtl_base_globals_size, 4\");", + "asm(\"rtems__rtl_base_globals_size:\");", + "asm(\" .long rtems__rtl_base_globals_size - rtems__rtl_base_globals\");", "", - "void rtems_rtl_base_sym_global_add (const unsigned char* , unsigned int );", 0 }; static const char* c_rtl_call_body[] = { "{", - "#if __bfin__ || __h8300__ || __v850__", - " rtems_rtl_base_sym_global_add (_rtems_rtl_base_globals,", - " _rtems_rtl_base_globals_size);", - "#else", - " rtems_rtl_base_sym_global_add (__rtems_rtl_base_globals,", - " __rtems_rtl_base_globals_size);", - "#endif", + " rtems_rtl_base_sym_global_add ((const unsigned char*) &rtems__rtl_base_globals,", + " rtems__rtl_base_globals_size);", "}", 0 }; @@ -118,7 +121,6 @@ temporary_file_paint (rld::process::tempfile& t, const char* lines[]) static void c_constructor_trailer (rld::process::tempfile& c) { - temporary_file_paint (c, c_trailer); c.write_line ("static void init(void) __attribute__ ((constructor));"); c.write_line ("static void init(void)"); temporary_file_paint (c, c_rtl_call_body); @@ -128,9 +130,8 @@ c_constructor_trailer (rld::process::tempfile& c) * The embedded trailer. */ static void -c_embedded_trailer(rld::process::tempfile& c) +c_embedded_trailer (rld::process::tempfile& c) { - temporary_file_paint (c, c_trailer); c.write_line ("void rtems_rtl_base_global_syms_init(void);"); c.write_line ("void rtems_rtl_base_global_syms_init(void)"); temporary_file_paint (c, c_rtl_call_body); @@ -141,40 +142,34 @@ c_embedded_trailer(rld::process::tempfile& c) * a running RTEMS machine. */ static void -generate_asm (rld::process::tempfile& c, - rld::symbols::table& symbols, - bool embed) +generate_c (rld::process::tempfile& c, + rld::symbols::table& symbols, + bool embed) { temporary_file_paint (c, c_header); - for (rld::symbols::symtab::const_iterator si = symbols.externals ().begin (); - si != symbols.externals ().end (); + for (rld::symbols::symtab::const_iterator si = symbols.globals ().begin (); + si != symbols.globals ().end (); ++si) { const rld::symbols::symbol& sym = *((*si).second); - if (!sym.name ().empty ()) - { - c.write_line ("asm(\" .asciz \\\"" + sym.name () + "\\\"\");"); + c.write_line ("asm(\" .asciz \\\"" + sym.name () + "\\\"\");"); - if (embed) - { - c.write_line ("#if __mips__"); - c.write_line ("asm(\" .align 0\");"); - c.write_line ("#else"); - c.write_line ("asm(\" .balign 1\");"); - c.write_line ("#endif"); - c.write_line ("asm(\" .long " + sym.name () + "\");"); - } - else - { - std::stringstream oss; - oss << std::hex << std::setfill ('0') << std::setw (8) << sym.value (); - c.write_line ("asm(\" .long 0x" + oss.str () + "\");"); - } + if (embed) + { + c.write_line ("asm(\" .long " + sym.name () + "\");"); + } + else + { + std::stringstream oss; + oss << std::hex << std::setfill ('0') << std::setw (8) << sym.value (); + c.write_line ("asm(\" .long 0x" + oss.str () + "\");"); } } + temporary_file_paint (c, c_trailer); + if (embed) c_embedded_trailer (c); else @@ -192,7 +187,7 @@ generate_symmap (rld::process::tempfile& c, if (rld::verbose ()) std::cout << "symbol C file: " << c.name () << std::endl; - generate_asm (c, symbols, embed); + generate_c (c, symbols, embed); if (rld::verbose ()) std::cout << "symbol O file: " << output << std::endl; @@ -203,7 +198,6 @@ generate_symmap (rld::process::tempfile& c, rld::cc::append_flags (rld::cc::ft_cflags, args); args.push_back ("-O2"); - args.push_back ("-g"); args.push_back ("-c"); args.push_back ("-o"); args.push_back (output); @@ -218,6 +212,7 @@ generate_symmap (rld::process::tempfile& c, out.name (), err.name ()); + if ((status.type != rld::process::status::normal) || (status.code != 0)) { @@ -324,7 +319,7 @@ main (int argc, char* argv[]) while (true) { - int opt = ::getopt_long (argc, argv, "hvVwS:o:m:E:c:C:", rld_opts, NULL); + int opt = ::getopt_long (argc, argv, "hvVwkef:S:o:m:E:c:C:", rld_opts, NULL); if (opt < 0) break; @@ -408,8 +403,8 @@ main (int argc, char* argv[]) throw rld::error ("no kernel file", "options"); if (argc != 1) throw rld::error ("only one kernel file", "options"); - if (output.empty ()) - throw rld::error ("no output file", "options"); + if (output.empty () && map.empty ()) + throw rld::error ("no output or map", "options"); kernel_name = *argv; @@ -421,6 +416,9 @@ main (int argc, char* argv[]) */ try { + /* + * Load the kernel ELF file symbol table. + */ kernel.open (); kernel.add (kernel_name); kernel.load_symbols (symbols, true); @@ -436,21 +434,8 @@ main (int argc, char* argv[]) if (!rld::cc::is_cc_set () && !rld::cc::is_exec_prefix_set ()) rld::cc::set_exec_prefix (rld::elf::machine_type ()); - rld::process::tempfile c (".c"); - - if (!symc.empty ()) - { - c.override (symc); - c.keep (); - } - - /* - * Generate and compile the symbol map. - */ - generate_symmap (c, output, symbols, embed); - /* - * Create a map file is asked to. + * Create a map file if asked too. */ if (!map.empty ()) { @@ -465,6 +450,25 @@ main (int argc, char* argv[]) mout.close (); } + /* + * Create an output file if asked too. + */ + if (!output.empty ()) + { + rld::process::tempfile c (".c"); + + if (!symc.empty ()) + { + c.override (symc); + c.keep (); + } + + /* + * Generate and compile the symbol map. + */ + generate_symmap (c, output, symbols, embed); + } + kernel.close (); } catch (...) diff --git a/rtemstoolkit/rld-files.cpp b/rtemstoolkit/rld-files.cpp index 03310e8..995b059 100644 --- a/rtemstoolkit/rld-files.cpp +++ b/rtemstoolkit/rld-files.cpp @@ -1040,10 +1040,32 @@ namespace rld rld::symbols::pointers syms; - elf ().get_symbols (syms, false, local, false, true); + if (local) + { + elf ().get_symbols (syms, false, true, false, false); + + if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) + std::cout << "object:load-sym: local: total " + << syms.size () << std::endl; + + for (symbols::pointers::iterator si = syms.begin (); + si != syms.end (); + ++si) + { + symbols::symbol& sym = *(*si); + + if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) + std::cout << "object:load-sym: local: " << sym << std::endl; + + sym.set_object (*this); + symbols.add_local (sym); + } + } + + elf ().get_symbols (syms, false, false, true, false); if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: exported: total " + std::cout << "object:load-sym: weak: total " << syms.size () << std::endl; for (symbols::pointers::iterator si = syms.begin (); @@ -1053,17 +1075,17 @@ namespace rld symbols::symbol& sym = *(*si); if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: exported: " << sym << std::endl; + std::cout << "object:load-sym: weak: " << sym << std::endl; sym.set_object (*this); - symbols.add_external (sym); + symbols.add_weak (sym); externals.push_back (&sym); } - elf ().get_symbols (syms, false, false, true, false); + elf ().get_symbols (syms, false, false, false, true); if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: weak: total " + std::cout << "object:load-sym: global: total " << syms.size () << std::endl; for (symbols::pointers::iterator si = syms.begin (); @@ -1073,10 +1095,10 @@ namespace rld symbols::symbol& sym = *(*si); if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: weak: " << sym << std::endl; + std::cout << "object:load-sym: global: " << sym << std::endl; sym.set_object (*this); - symbols.add_weak (sym); + symbols.add_global (sym); externals.push_back (&sym); } diff --git a/rtemstoolkit/rld-process.cpp b/rtemstoolkit/rld-process.cpp index bfd6734..e91796f 100644 --- a/rtemstoolkit/rld-process.cpp +++ b/rtemstoolkit/rld-process.cpp @@ -271,7 +271,7 @@ namespace rld { if (level < (sizeof (buf) - 1)) { - memset (buf + level, 0, sizeof (buf) - level); + ::memset (buf + level, 0, sizeof (buf) - level); int read = ::read (fd, buf + level, sizeof (buf) - level - 1); if (read < 0) throw rld::error (::strerror (errno), "tempfile read:" + _name); @@ -285,15 +285,14 @@ namespace rld char* lf = ::strchr (buf, '\n'); int len = level; if (lf) - len = lf - &buf[0] + 1; - if (lf || !reading) { - line.append (buf, len); - level -= len; + len = lf - &buf[0] + 1; + reading = false; } + line.append (buf, len); + level -= len; if (level) ::memmove (buf, &buf[len], level + 1); - reading = false; } } } @@ -354,7 +353,7 @@ namespace rld { read_line (line); ++lc; - if (line.empty ()) + if (line.empty () && (level == 0)) break; if (!prefix.empty ()) out << prefix << ": "; diff --git a/rtemstoolkit/rld-resolver.cpp b/rtemstoolkit/rld-resolver.cpp index d2a9f1e..e837af1 100644 --- a/rtemstoolkit/rld-resolver.cpp +++ b/rtemstoolkit/rld-resolver.cpp @@ -108,7 +108,7 @@ namespace rld if ((urs.binding () != STB_WEAK) && urs.object ()) continue; - symbols::symbol* es = base_symbols.find_external (urs.name ()); + symbols::symbol* es = base_symbols.find_global (urs.name ()); bool base = true; if (rld::verbose () >= RLD_VERBOSE_INFO) @@ -120,7 +120,7 @@ namespace rld if (!es) { - es = symbols.find_external (urs.name ()); + es = symbols.find_global (urs.name ()); if (!es) { es = symbols.find_weak (urs.name ()); diff --git a/rtemstoolkit/rld-symbols.cpp b/rtemstoolkit/rld-symbols.cpp index 79212db..081d3e1 100644 --- a/rtemstoolkit/rld-symbols.cpp +++ b/rtemstoolkit/rld-symbols.cpp @@ -132,6 +132,24 @@ namespace rld return (name_[0] == '_') && (name_[1] == 'Z'); } + bool + symbol::is_local () const + { + return binding () == STB_LOCAL; + } + + bool + symbol::is_weak () const + { + return binding () == STB_WEAK; + } + + bool + symbol::is_global () const + { + return binding () == STB_GLOBAL; + } + int symbol::type () const { @@ -275,22 +293,28 @@ namespace rld } void - table::add_external (symbol& sym) + table::add_global (symbol& sym) { - _externals[sym.name ()] = &sym; + globals_[sym.name ()] = &sym; } void table::add_weak (symbol& sym) { - _weaks[sym.name ()] = &sym; + weaks_[sym.name ()] = &sym; + } + + void + table::add_local (symbol& sym) + { + locals_[sym.name ()] = &sym; } symbol* - table::find_external (const std::string& name) + table::find_global (const std::string& name) { - symtab::iterator sti = _externals.find (name); - if (sti == _externals.end ()) + symtab::iterator sti = globals_.find (name); + if (sti == globals_.end ()) return 0; return (*sti).second; } @@ -298,8 +322,17 @@ namespace rld symbol* table::find_weak (const std::string& name) { - symtab::iterator sti = _weaks.find (name); - if (sti == _weaks.end ()) + symtab::iterator sti = weaks_.find (name); + if (sti == weaks_.end ()) + return 0; + return (*sti).second; + } + + symbol* + table::find_local (const std::string& name) + { + symtab::iterator sti = locals_.find (name); + if (sti == locals_.end ()) return 0; return (*sti).second; } @@ -307,19 +340,25 @@ namespace rld size_t table::size () const { - return _externals.size () + _weaks.size (); + return globals_.size () + weaks_.size () + locals_.size (); } const symtab& - table::externals () const + table::globals () const { - return _externals; + return globals_; } const symtab& table::weaks () const { - return _weaks; + return weaks_; + } + + const symtab& + table::locals () const + { + return locals_; } void @@ -329,7 +368,7 @@ namespace rld sbi != bucket_.end (); ++sbi) { - table_.add_external (*sbi); + table_.add_global (*sbi); } } @@ -364,10 +403,12 @@ namespace rld void output (std::ostream& out, const table& symbols) { - out << "Externals:" << std::endl; - output (out, symbols.externals ()); + out << "Globals:" << std::endl; + output (out, symbols.globals ()); out << "Weaks:" << std::endl; output (out, symbols.weaks ()); + out << "Locals:" << std::endl; + output (out, symbols.locals ()); } void diff --git a/rtemstoolkit/rld-symbols.h b/rtemstoolkit/rld-symbols.h index 5405d2f..02a41a3 100644 --- a/rtemstoolkit/rld-symbols.h +++ b/rtemstoolkit/rld-symbols.h @@ -100,6 +100,21 @@ namespace rld */ bool is_cplusplus () const; + /** + * Is the symbol binding is local ? + */ + bool is_local () const; + + /** + * Is the symbol binding weak ? + */ + bool is_weak () const; + + /** + * Is the symbol binding global ? + */ + bool is_global () const; + /** * The symbol's type. */ @@ -190,7 +205,7 @@ namespace rld typedef std::map < std::string, symbol* > symtab; /** - * A symbols contains a symbol table of externals and weak symbols. + * A symbols contains a symbol table of global, weak and local symbols. */ class table { @@ -206,9 +221,9 @@ namespace rld ~table (); /** - * Add an external symbol. + * Add a global symbol. */ - void add_external (symbol& sym); + void add_global (symbol& sym); /** * Add a weak symbol. @@ -216,30 +231,45 @@ namespace rld void add_weak (symbol& sym); /** - * Find an external symbol. + * Add a local symbol. */ - symbol* find_external (const std::string& name); + void add_local (symbol& sym); + + /** + * Find a global symbol. + */ + symbol* find_global (const std::string& name); /** * Find an weak symbol. */ symbol* find_weak (const std::string& name); + /** + * Find an local symbol. + */ + symbol* find_local (const std::string& name); + /** * Return the size of the symbols loaded. */ size_t size () const; /** - * Return the externals symbol table. + * Return the globals symbol table. */ - const symtab& externals () const; + const symtab& globals () const; /** * Return the weaks symbol table. */ const symtab& weaks () const; + /** + * Return the locals symbol table. + */ + const symtab& locals () const; + private: /** @@ -248,14 +278,19 @@ namespace rld table (const table& orig); /** - * A table of external symbols. + * A table of global symbols. */ - symtab _externals; + symtab globals_; /** * A table of weak symbols. */ - symtab _weaks; + symtab weaks_; + + /** + * A table of local symbols. + */ + symtab locals_; }; /** diff --git a/rtemstoolkit/rtems-utils.h b/rtemstoolkit/rtems-utils.h index 9918570..4ce9c68 100644 --- a/rtemstoolkit/rtems-utils.h +++ b/rtemstoolkit/rtems-utils.h @@ -22,8 +22,8 @@ * */ -#if !defined (_MEMORY_DUMP_H_) -#define _MEMORY_DUMP_H_ +#if !defined (_RTEMS_UTILS_H_) +#define _RTEMS_UTILS_H_ #include -- cgit v1.2.3