diff options
Diffstat (limited to 'linkers/rld-files.cpp')
-rw-r--r-- | linkers/rld-files.cpp | 1586 |
1 files changed, 0 insertions, 1586 deletions
diff --git a/linkers/rld-files.cpp b/linkers/rld-files.cpp deleted file mode 100644 index 03310e8..0000000 --- a/linkers/rld-files.cpp +++ /dev/null @@ -1,1586 +0,0 @@ -/* - * Copyright (c) 2011, Chris Johns <chrisj@rtems.org> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <algorithm> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <rld.h> - -#if __WIN32__ -#define CREATE_MODE (S_IRUSR | S_IWUSR) -#define OPEN_FLAGS (O_BINARY) -#else -#define CREATE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) -#define OPEN_FLAGS (0) -#endif - -namespace rld -{ - namespace files - { - /** - * Scan the decimal number returning the value found. - */ - uint64_t - scan_decimal (const uint8_t* string, size_t len) - { - uint64_t value = 0; - - while (len && (*string != ' ')) - { - value *= 10; - value += *string - '0'; - ++string; - --len; - } - - return value; - } - - void - set_number (uint32_t value, uint8_t* string, size_t len, bool octal = false) - { - std::ostringstream oss; - if (octal) - oss << std::oct; - oss << value; - size_t l = oss.str ().length (); - if (l > len) - l = len; - memcpy (string, oss.str ().c_str (), l); - } - - file::file (const std::string& aname, - const std::string& oname, - off_t offset, - size_t size) - : aname_ (aname), - oname_ (oname), - offset_ (offset), - size_ (size) - { - } - - file::file (const std::string& path, bool is_object) - : offset_ (0), - size_ (0) - { - set (path, is_object); - } - - file::file () - : offset_ (0), - size_ (0) - { - } - - void - file::set (const std::string& path, bool is_object) - { - /* - * If there is a path look for a colon. If there is no colon we assume - * it is an object file. If the colon is the last character in the path - * it is just an archive. - */ - if (!path.empty ()) - { - bool get_size = false; - if (is_object) - { - size_t colon = path.find_last_of (':'); - if ((colon != std::string::npos) && (colon > RLD_DRIVE_SEPARATOR)) - { - aname_ = path.substr (0, colon - 1); - oname_ = path.substr (colon + 1); - // @todo Add offset scanning. - } - else - { - oname_ = path; - get_size = true; - } - } - else - { - aname_ = path; - get_size = true; - } - - if (get_size) - { - struct stat sb; - if (::stat (path.c_str (), &sb) == 0) - size_ = sb.st_size; - } - } - } - - bool - file::is_archive () const - { - return !aname_.empty () && oname_.empty (); - } - - bool - file::is_object () const - { - return !oname_.empty (); - } - - bool - file::is_valid () const - { - return !aname_.empty () || !oname_.empty (); - } - - bool - file::exists () const - { - /* - * No name set returns false. - */ - bool result = false; - const std::string p = path (); - if (!p.empty ()) - result = path::check_file (p); - return result; - } - - const std::string - file::path () const - { - if (!aname_.empty ()) - return aname_; - return oname_; - } - - const std::string - file::full () const - { - std::string f; - if (!aname_.empty ()) - { - f = aname_; - if (!oname_.empty ()) - f += ':'; - } - if (!oname_.empty ()) - f += oname_; - if (!aname_.empty () && !oname_.empty ()) - f += '@' + rld::to_string (offset_); - return f; - } - - const std::string - file::basename () const - { - return rld::path::basename (full ()); - } - - const std::string& - file::aname () const - { - return aname_; - } - - const std::string& - file::oname () const - { - return oname_; - } - - off_t - file::offset () const - { - return offset_; - } - - size_t - file::size () const - { - return size_; - } - - image::image (file& name) - : name_ (name), - references_ (0), - fd_ (-1), - symbol_refs (0), - writable (false) - { - } - - image::image (const std::string& path, bool is_object) - : name_ (path, is_object), - references_ (0), - fd_ (-1), - symbol_refs (0), - writable (false) - { - } - - image::image () - : references_ (0), - fd_ (-1), - symbol_refs (0), - writable (false) - { - } - - image::~image () - { - if (references_) - throw rld_error_at ("references when destructing image"); - if (fd_ >= 0) - ::close (fd_); - } - - void - image::open (file& name) - { - name_ = name; - open (); - } - - void - image::open (bool writable_) - { - const std::string path = name_.path (); - - if (path.empty ()) - throw rld::error ("No file name", "open:" + path); - - if (rld::verbose () >= RLD_VERBOSE_TRACE_FILE) - std::cout << "image::open: " << name (). full () - << " refs:" << references_ + 1 - << " writable:" << (char*) (writable_ ? "yes" : "no") - << std::endl; - - if (fd_ < 0) - { - writable = writable_; - - if (writable) - fd_ = ::open (path.c_str (), OPEN_FLAGS | O_RDWR | O_CREAT | O_TRUNC, CREATE_MODE); - else - fd_ = ::open (path.c_str (), OPEN_FLAGS | O_RDONLY); - if (fd_ < 0) - throw rld::error (::strerror (errno), "open:" + path); - } - else - { - if (writable_ != writable) - throw rld::error ("Cannot change write status", "open:" + path); - } - - ++references_; - } - - void - image::close () - { - if (references_ > 0) - { - if (rld::verbose () >= RLD_VERBOSE_TRACE_FILE) - std::cout << "image::close: " << name ().full () - << " refs:" << references_ << std::endl; - - --references_; - if (references_ == 0) - { - ::close (fd_); - fd_ = -1; - } - } - } - - ssize_t - image::read (void* buffer_, size_t size) - { - uint8_t* buffer = static_cast <uint8_t*> (buffer_); - size_t have_read = 0; - size_t to_read = size; - while (have_read < size) - { - const ssize_t rsize = ::read (fd (), buffer, to_read); - if (rsize < 0) - throw rld::error (strerror (errno), "read:" + name ().path ()); - if (rsize == 0) - break; - have_read += rsize; - to_read -= rsize; - buffer += rsize; - } - return have_read; - } - - ssize_t - image::write (const void* buffer_, size_t size) - { - const uint8_t* buffer = static_cast <const uint8_t*> (buffer_); - size_t have_written = 0; - size_t to_write = size; - while (have_written < size) - { - const ssize_t wsize = ::write (fd (), buffer, to_write); - if (wsize < 0) - throw rld::error (strerror (errno), "write:" + name ().path ()); - have_written += wsize; - to_write -= wsize; - buffer += wsize; - } - return have_written; - } - - void - image::seek (off_t offset) - { - if (::lseek (fd (), name_.offset () + offset, SEEK_SET) < 0) - throw rld::error (strerror (errno), "lseek:" + name ().path ()); - } - - bool - image::seek_read (off_t offset, uint8_t* buffer, size_t size) - { - seek (offset); - return size == (size_t) read (buffer, size); - } - - bool - image::seek_write (off_t offset, const void* buffer, size_t size) - { - seek (offset); - return size == (size_t) write (buffer, size); - } - - const file& - image::name () const - { - return name_; - } - - int - image::references () const - { - return references_; - } - - size_t - image::size () const - { - return name ().size (); - } - - int - image::fd () const - { - return fd_; - } - - rld::elf::file& - image::elf () - { - return elf_; - } - - void - image::symbol_referenced () - { - ++symbol_refs; - } - - int - image::symbol_references () const - { - return symbol_refs; - } - - void - copy_file (image& in, image& out, size_t size) - { - #define COPY_FILE_BUFFER_SIZE (8 * 1024) - uint8_t* buffer = 0; - - if (size == 0) - size = in.name ().size (); - - try - { - buffer = new uint8_t[COPY_FILE_BUFFER_SIZE]; - while (size) - { - /* - * @fixme the reading and writing are not POSIX; sigints could split them. - */ - - size_t l = size < COPY_FILE_BUFFER_SIZE ? size : COPY_FILE_BUFFER_SIZE; - ssize_t r = ::read (in.fd (), buffer, l); - - if (r < 0) - throw rld::error (::strerror (errno), "reading: " + in.name ().full ()); - - if (r == 0) - { - std::ostringstream oss; - oss << "reading: " + in.name ().full () << " (" << size << ')'; - throw rld::error ("input too short", oss.str ()); - } - - ssize_t w = ::write (out.fd (), buffer, r); - - if (w < 0) - throw rld::error (::strerror (errno), "writing: " + out.name ().full ()); - - if (w != r) - throw rld::error ("output trucated", "writing: " + out.name ().full ()); - - size -= r; - } - } - catch (...) - { - delete [] buffer; - throw; - } - - if (buffer) - delete [] buffer; - } - - /** - * Defines for the header of an archive. - */ - #define rld_archive_ident "!<arch>\n" - #define rld_archive_ident_size (sizeof (rld_archive_ident) - 1) - #define rld_archive_fhdr_base rld_archive_ident_size - #define rld_archive_fname (0) - #define rld_archive_fname_size (16) - #define rld_archive_mtime (16) - #define rld_archive_mtime_size (12) - #define rld_archive_uid (28) - #define rld_archive_uid_size (6) - #define rld_archive_gid (34) - #define rld_archive_gid_size (6) - #define rld_archive_mode (40) - #define rld_archive_mode_size (8) - #define rld_archive_size (48) - #define rld_archive_size_size (10) - #define rld_archive_magic (58) - #define rld_archive_magic_size (2) - #define rld_archive_fhdr_size (60) - #define rld_archive_max_file_size (1024) - - archive::archive (const std::string& path) - : image (path, false) - { - if (!name ().is_valid ()) - throw rld_error_at ("name is empty"); - if (!name ().is_archive ()) - throw rld_error_at ("name is not an archive: " + name ().oname ()); - } - - archive::~archive () - { - end (); - close (); - } - - void - archive::begin () - { - if (references () == 1) - { - elf ().begin (name ().full (), fd ()); - - /* - * Make sure it is an archive. - */ - if (!elf ().is_archive ()) - throw rld::error ("Not an archive.", - "archive-begin:" + name ().full ()); - } - } - - void - archive::end () - { - if (references () == 1) - elf ().end (); - } - - bool - archive::is (const std::string& path) const - { - return name ().path () == path; - } - - bool - archive::is_valid () - { - open (); - uint8_t header[rld_archive_ident_size]; - seek_read (0, &header[0], rld_archive_ident_size); - bool result = ::memcmp (header, rld_archive_ident, - rld_archive_ident_size) == 0 ? true : false; - close (); - return result; - } - - void - archive::load_objects (objects& objs) - { - off_t extended_file_names = 0; - off_t offset = rld_archive_fhdr_base; - size_t size = 0; - - while (true) - { - uint8_t header[rld_archive_fhdr_size]; - - if (!read_header (offset, &header[0])) - break; - - /* - * The archive file headers are always aligned to an even address. - */ - size = - (scan_decimal (&header[rld_archive_size], - rld_archive_size_size) + 1) & ~1; - - /* - * Check for the GNU extensions. - */ - if (header[0] == '/') - { - off_t extended_off; - - switch (header[1]) - { - case ' ': - /* - * Symbols table. Ignore the table. - */ - break; - case '/': - /* - * Extended file names table. Remember. - */ - extended_file_names = offset + rld_archive_fhdr_size; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* - * Offset into the extended file name table. If we do not have the - * offset to the extended file name table find it. - */ - extended_off = scan_decimal (&header[1], rld_archive_fname_size); - - if (extended_file_names == 0) - { - off_t off = offset; - while (extended_file_names == 0) - { - size_t esize = - (scan_decimal (&header[rld_archive_size], - rld_archive_size_size) + 1) & ~1; - off += esize + rld_archive_fhdr_size; - - if (!read_header (off, &header[0])) - throw rld::error ("No GNU extended file name section found", - "get-names:" + name ().path ()); - - if ((header[0] == '/') && (header[1] == '/')) - { - extended_file_names = off + rld_archive_fhdr_size; - break; - } - } - } - - if (extended_file_names) - { - /* - * We know the offset in the archive to the extended file. Read - * the name from the table and compare with the name we are - * after. - */ - char cname[rld_archive_max_file_size]; - seek_read (extended_file_names + extended_off, - (uint8_t*) &cname[0], rld_archive_max_file_size); - add_object (objs, cname, - offset + rld_archive_fhdr_size, size); - } - break; - default: - /* - * Ignore the file because we do not know what it it. - */ - break; - } - } - else - { - /* - * Normal archive name. - */ - add_object (objs, - (char*) &header[rld_archive_fname], - offset + rld_archive_fhdr_size, size); - } - - offset += size + rld_archive_fhdr_size; - } - } - - bool - archive::operator< (const archive& rhs) const - { - return name ().path () < rhs.name ().path (); - } - - bool - archive::read_header (off_t offset, uint8_t* header) - { - if (!seek_read (offset, header, rld_archive_fhdr_size)) - return false; - - if ((header[rld_archive_magic] != 0x60) || - (header[rld_archive_magic + 1] != 0x0a)) - throw rld::error ("Invalid header magic numbers at " + - rld::to_string (offset), "read-header:" + name ().path ()); - - return true; - } - - void - archive::add_object (objects& objs, const char* path, off_t offset, size_t size) - { - const char* end = path; - while ((*end != '\0') && (*end != '/') && (*end != '\n')) - ++end; - - std::string str; - str.append (path, end - path); - - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << "archive::add-object: " << str << std::endl; - - file n (name ().path (), str, offset, size); - objs[n.full()] = new object (*this, n); - } - - void - archive::write_header (const std::string& name, - uint32_t mtime, - int uid, - int gid, - int mode, - size_t size) - { - uint8_t header[rld_archive_fhdr_size]; - - memset (header, ' ', sizeof (header)); - - size_t len = name.length (); - if (len > rld_archive_fname_size) - len = rld_archive_fname_size; - memcpy (&header[rld_archive_fname], &name[0], len); - - set_number (mtime, header + rld_archive_mtime, rld_archive_mtime_size); - set_number (uid, header + rld_archive_uid, rld_archive_uid_size); - set_number (gid, header + rld_archive_gid, rld_archive_gid_size); - set_number (mode, header + rld_archive_mode, rld_archive_mode_size, true); - set_number (size, header + rld_archive_size, rld_archive_size_size); - - header[rld_archive_magic] = 0x60; - header[rld_archive_magic + 1] = 0x0a; - - write (header, sizeof (header)); - } - - void - archive::create (object_list& objects) - { - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - std::cout << "archive::create: " << name ().full () - << ", objects: " << objects.size () << std::endl; - - open (true); - - try - { - seek_write (0, rld_archive_ident, rld_archive_ident_size); - - /* - * GNU extended filenames. - */ - std::string extended_file_names; - - for (object_list::iterator oi = objects.begin (); - oi != objects.end (); - ++oi) - { - object& obj = *(*oi); - const std::string& oname = path::basename (obj.name ().oname ()); - if (oname.length () >= rld_archive_fname_size) - extended_file_names += oname + '\n'; - } - - if (!extended_file_names.empty ()) - { - if (extended_file_names.length () & 1) - { - extended_file_names += ' '; - } - write_header ("//", 0, 0, 0, 0, extended_file_names.length ()); - write (extended_file_names.c_str (), extended_file_names.length ()); - } - - for (object_list::iterator oi = objects.begin (); - oi != objects.end (); - ++oi) - { - object& obj = *(*oi); - - obj.open (); - - try - { - std::string oname = path::basename (obj.name ().oname ()); - - /* - * Convert the file name to an offset into the extended file name - * table if the file name is too long for the header. - */ - - if (oname.length () >= rld_archive_fname_size) - { - size_t pos = extended_file_names.find (oname + '\n'); - if (pos == std::string::npos) - throw rld_error_at ("extended file name not found"); - std::ostringstream oss; - oss << '/' << pos; - oname = oss.str (); - } - else oname += '/'; - - write_header (oname, 0, 0, 0, 0666, (obj.name ().size () + 1) & ~1); - obj.seek (0); - copy_file (obj, *this); - if (obj.name ().size () & 1) - write ("\n", 1); - } - catch (...) - { - obj.close (); - throw; - } - - obj.close (); - } - } - catch (...) - { - close (); - throw; - } - - close (); - } - - relocation::relocation (const elf::relocation& er) - : offset (er.offset ()), - type (er.type ()), - info (er.info ()), - addend (er.addend ()), - symname (er.symbol ().name ()), - symtype (er.symbol ().type ()), - symsect (er.symbol ().section_index ()), - symvalue (er.symbol ().value ()), - symbinding (er.symbol ().binding ()) - { - } - - section::section (const elf::section& es) - : name (es.name ()), - index (es.index ()), - type (es.type ()), - size (es.size ()), - alignment (es.alignment ()), - link (es.link ()), - info (es.info ()), - flags (es.flags ()), - offset (es.offset ()), - rela (es.get_reloc_type ()) - { - } - - void - section::load_relocations (const elf::section& es) - { - const elf::relocations& es_relocs = es.get_relocations (); - for (elf::relocations::const_iterator ri = es_relocs.begin (); - ri != es_relocs.end (); - ++ri) - { - relocs.push_back (relocation (*ri)); - } - rela = es.get_reloc_type (); - } - - size_t - sum_sizes (const sections& secs) - { - size_t size = 0; - - for (sections::const_iterator si = secs.begin (); - si != secs.end (); - ++si) - { - const section& sec = *si; - - if ((size % sec.alignment) != 0) - size -= (size % sec.alignment) + sec.alignment; - size += sec.size; - } - - return size; - } - - const section* - find (const sections& secs, const int index) - { - for (sections::const_iterator si = secs.begin (); - si != secs.end (); - ++si) - { - const section& sec = *si; - - if (index == sec.index) - return &sec; - } - - return 0; - } - - object::object (archive& archive_, file& name_) - : image (name_), - archive_ (&archive_), - valid_ (false), - resolving_ (false), - resolved_ (false) - { - if (!name ().is_valid ()) - throw rld_error_at ("name is empty"); - } - - object::object (const std::string& path) - : image (path), - archive_ (0), - valid_ (false), - resolving_ (false), - resolved_ (false) - { - if (!name ().is_valid ()) - throw rld_error_at ("name is empty"); - } - - object::object () - : archive_ (0), - valid_ (false), - resolving_ (false), - resolved_ (false) - { - } - - object::~object () - { - end (); - close (); - } - - void - object::open (bool writable) - { - if (archive_) - { - if (writable) - throw rld_error_at ("object files in archives are not writable"); - archive_->open (); - } - else - image::open (writable); - } - - void - object::close () - { - if (archive_) - { - archive_->end (); - archive_->close (); - } - else - { - end (); - image::close (); - } - } - - void - object::begin () - { - /* - * Begin a session. - */ - - if (rld::verbose () >= RLD_VERBOSE_TRACE_FILE) - std::cout << "object:begin: " << name ().full () << " in-archive:" - << ((char*) (archive_ ? "yes" : "no")) << std::endl; - - if (archive_) - elf ().begin (name ().full (), archive_->elf(), name ().offset ()); - else - elf ().begin (name ().full (), fd (), is_writable ()); - - /* - * Cannot be an archive. - */ - if (elf ().is_archive ()) - throw rld::error ("Is an archive not an object file.", - "object-begin:" + name ().full ()); - - /* - * We only support executable or relocatable ELF files. - */ - if (!is_writable ()) - { - if (!elf ().is_executable () && !elf ().is_relocatable ()) - throw rld::error ("Invalid ELF type (only ET_EXEC/ET_REL supported).", - "object-begin:" + name ().full ()); - - elf::check_file (elf ()); - - /** - * We assume the ELF file is invariant over the linking process. - */ - - if (secs.empty ()) - { - elf::sections elf_secs; - - elf ().get_sections (elf_secs, 0); - - for (elf::sections::const_iterator esi = elf_secs.begin (); - esi != elf_secs.end (); - ++esi) - { - secs.push_back (section (*(*esi))); - } - } - } - - /* - * This is a valid object file. The file format checks out. - */ - valid_ = true; - } - - void - object::end () - { - if (rld::verbose () >= RLD_VERBOSE_TRACE_FILE) - std::cout << "object:end: " << name ().full () << std::endl; - - elf ().end (); - } - - bool - object::valid () const - { - return valid_; - } - - void - object::load_symbols (rld::symbols::table& symbols, bool local) - { - if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: " << name ().full () << std::endl; - - rld::symbols::pointers syms; - - elf ().get_symbols (syms, false, local, false, true); - - if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: exported: 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: exported: " << sym << std::endl; - - sym.set_object (*this); - symbols.add_external (sym); - externals.push_back (&sym); - } - - elf ().get_symbols (syms, false, false, true, false); - - if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: weak: 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: weak: " << sym << std::endl; - - sym.set_object (*this); - symbols.add_weak (sym); - externals.push_back (&sym); - } - - elf ().get_symbols (syms, true, false, true, true); - - if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS) - std::cout << "object:load-sym: unresolved: 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: unresolved: "; - sym.output (std::cout); - std::cout << std::endl; - } - - unresolved[sym.name ()] = &sym; - } - } - - void - object::load_relocations () - { - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "object:load-relocs: " << name ().full () << std::endl; - - elf ().load_relocations (); - - for (sections::iterator si = secs.begin (); - si != secs.end (); - ++si) - { - section& sec = *si; - const elf::section& elf_sec = elf ().get_section (sec.index); - sec.load_relocations (elf_sec); - } - } - - int - object::references () const - { - if (archive_) - return archive_->references (); - return image::references (); - } - - size_t - object::size () const - { - if (archive_) - return archive_->size (); - return image::size (); - } - - int - object::fd () const - { - if (archive_) - return archive_->fd (); - return image::fd (); - } - - void - object::symbol_referenced () - { - image::symbol_referenced (); - if (archive_) - archive_->symbol_referenced (); - } - - archive* - object::get_archive () - { - return archive_; - } - - rld::symbols::symtab& - object::unresolved_symbols () - { - return unresolved; - } - - rld::symbols::pointers& - object::external_symbols () - { - return externals; - } - - void - object::get_sections (sections& filtered_secs, - uint32_t type, - uint64_t flags_in, - uint64_t flags_out) - { - for (sections::const_iterator si = secs.begin (); - si != secs.end (); - ++si) - { - const section& sec = *si; - if ((type == 0) || (type == sec.type)) - { - if ((flags_in == 0) || - (((sec.flags & flags_in) == flags_in) && - ((sec.flags & flags_out) == 0))) - { - filtered_secs.push_back (sec); - } - } - } - } - - void - object::get_sections (sections& filtered_secs, const std::string& matching_name) - { - for (sections::const_iterator si = secs.begin (); - si != secs.end (); - ++si) - { - const section& sec = *si; - if (sec.name == matching_name) - { - filtered_secs.push_back (sec); - } - } - } - - const section& - object::get_section (int index) const - { - for (sections::const_iterator si = secs.begin (); - si != secs.end (); - ++si) - { - const section& sec = *si; - if (sec.index == index) - return sec; - } - - throw rld::error ("Section index '" + rld::to_string (index) + - "' not found: " + name ().full (), "object::get-section"); - } - - void - object::resolve_set () - { - resolving_ = true; - } - - void - object::resolve_clear () - { - resolving_ = false; - } - - bool - object::resolving () const - { - return resolving_; - } - - void - object::resolved_set () - { - resolved_ = true; - } - - bool - object::resolved () const - { - return resolved_; - } - - cache::cache () - : opened (false) - { - } - - cache::~cache () - { - close (); - } - - void - cache::open () - { - if (!opened) - { - collect_object_files (); - archives_begin (); - opened = true; - } - } - - void - cache::close () - { - if (opened) - { - /* - * Must delete the object first as they could depend on archives. - */ - for (objects::iterator oi = objects_.begin (); oi != objects_.end (); ++oi) - delete (*oi).second; - for (archives::iterator ai = archives_.begin (); ai != archives_.end (); ++ai) - delete (*ai).second; - opened = false; - } - } - - void - cache::add (const std::string& path) - { - paths_.push_back (path); - input (path); - } - - void - cache::add (path::paths& paths__) - { - for (path::paths::iterator pi = paths__.begin(); - pi != paths__.end(); - ++pi) - add (*pi); - } - - void - cache::add_libraries (path::paths& paths__) - { - for (path::paths::iterator pi = paths__.begin(); - pi != paths__.end(); - ++pi) - input (*pi); - } - - void - cache::archive_begin (const std::string& path) - { - archives::iterator ai = archives_.find (path); - if (ai != archives_.end ()) - { - archive* ar = (*ai).second; - if (!ar->is_open ()) - { - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "cache:archive-begin: " << path << std::endl; - ar->open (); - ar->begin (); - } - } - } - - void - cache::archive_end (const std::string& path) - { - archives::iterator ai = archives_.find (path); - if (ai != archives_.end ()) - { - archive* ar = (*ai).second; - if (ar->is_open ()) - { - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "cache:archive-end: " << path << std::endl; - ar->end (); - ar->close (); - } - } - } - - void - cache::archives_begin () - { - for (archives::iterator ai = archives_.begin (); ai != archives_.end (); ++ai) - archive_begin (((*ai).second)->path ()); - } - - void - cache::archives_end () - { - for (archives::iterator ai = archives_.begin (); ai != archives_.end (); ++ai) - archive_end (((*ai).second)->path ()); - } - - void - cache::collect_object_files () - { - for (path::paths::iterator ni = paths_.begin (); ni != paths_.end (); ++ni) - collect_object_files (*ni); - } - - void - cache::collect_object_files (const std::string& path) - { - archive* ar = new archive (path); - - if (ar->is_valid ()) - { - try - { - ar->open (); - ar->load_objects (objects_); - ar->close (); - archives_[path] = ar; - } - catch (...) - { - delete ar; - throw; - } - } - else - { - delete ar; - object* obj = new object (path); - if (!obj->name ().exists ()) - { - delete obj; - throw rld::error ("'" + path + "', Not found or a regular file.", - "file-check"); - } - try - { - obj->open (); - obj->begin (); - obj->end (); - obj->close (); - objects_[path] = obj; - } - catch (...) - { - delete obj; - throw; - } - } - } - - void - cache::load_symbols (rld::symbols::table& symbols, bool local) - { - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "cache:load-sym: object files: " << objects_.size () - << std::endl; - - for (objects::iterator oi = objects_.begin (); - oi != objects_.end (); - ++oi) - { - object* obj = (*oi).second; - obj->open (); - obj->begin (); - obj->load_symbols (symbols, local); - obj->end (); - obj->close (); - } - - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "cache:load-sym: symbols: " << symbols.size () - << std::endl; - } - - void - cache::output_unresolved_symbols (std::ostream& out) - { - for (objects::iterator oi = objects_.begin (); - oi != objects_.end (); - ++oi) - { - object* obj = (*oi).second; - if (obj) - { - out << obj->name ().full () << ':' << std::endl; - rld::symbols::output (out, obj->unresolved_symbols ()); - } - } - } - - archives& - cache::get_archives () - { - return archives_; - } - - objects& - cache::get_objects () - { - return objects_; - } - - void - cache::get_objects (object_list& list) const - { - list.clear (); - for (path::paths::const_iterator pi = paths_.begin (); - pi != paths_.end (); - ++pi) - { - objects::const_iterator oi = objects_.find (*pi); - if (oi == objects_.end ()) - throw rld_error_at ("path not found in objects"); - list.push_back ((*oi).second); - } - } - - const path::paths& - cache::get_paths () const - { - return paths_; - } - - int - cache::archive_count () const - { - return archives_.size (); - } - - int - cache::object_count () const - { - return objects_.size (); - } - - int - cache::path_count () const - { - return paths_.size (); - } - - void - cache::get_archive_files (files& afiles) - { - for (archives::iterator ai = archives_.begin (); ai != archives_.end (); ++ai) - afiles.push_back ((*ai).second->name ().full ()); - } - - void - cache::get_object_files (files& ofiles) - { - for (objects::iterator oi = objects_.begin (); oi != objects_.end (); ++oi) - ofiles.push_back ((*oi).second->name ()); - } - - void - cache::output_archive_files (std::ostream& out) - { - for (archives::iterator ai = archives_.begin (); ai != archives_.end (); ++ai) - out << ' ' << (*ai).second->name ().full () << std::endl; - } - - void - cache::output_object_files (std::ostream& out) - { - for (objects::iterator oi = objects_.begin (); oi != objects_.end (); ++oi) - out << ' ' << (*oi).second->name ().full () << std::endl; - } - - void - cache::input (const std::string& path) - { - if (opened) - { - collect_object_files (path); - archive_begin (path); - } - } - - void - find_libraries (path::paths& libraries, - path::paths& libpaths, - path::paths& libs) - { - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "Finding libraries:." << std::endl; - libraries.clear (); - for (path::paths::size_type l = 0; l < libs.size (); ++l) - { - std::string lib = "lib" + libs[l] + ".a"; - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - std::cout << " searching: " << lib << std::endl; - bool found = false; - for (path::paths::size_type p = 0; p < libpaths.size (); ++p) - { - std::string plib; - path::path_join (libpaths[p], lib, plib); - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - std::cout << " checking: " << plib << std::endl; - if (path::check_file (plib)) - { - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << " found: " << plib << std::endl; - libraries.push_back (plib); - found = true; - break; - } - } - - if (!found) - throw rld::error ("Not found", lib); - } - } - - } -} |