/* Copyright (C) 2021-2026 Free Software Foundation, Inc. Contributed by Oracle. This file is part of GNU Binutils. This program 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 3, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h"#include <unistd.h>#include <ar.h>#include <ctype.h>#include <sys/param.h> #include "util.h"#include "DbeSession.h"#include "Experiment.h"#include "DataObject.h"#include "Function.h"#include "DbeView.h"#include "MetricList.h"#include "Module.h"#include "ClassFile.h"#include "LoadObject.h"#include "Disasm.h"#include "CompCom.h"#include "Dwarf.h"#include "DbeFile.h"#include "PathTree.h"#include "Elf.h" Module::Module (){ lang_code = Sp_lang_unknown; flags = 0; status = AE_NOTREAD; openSourceFlag = AE_NOTREAD; hexVisible = false; disPath = NULL; stabsPath = NULL; stabsTmp = NULL; disName = NULL; stabsName = NULL; indexStabsLink = NULL; file_name = NULL; functions = new Vector<Function*>; loadobject = NULL; dot_o_file = NULL; main_source = dbeSession->get_Unknown_Source (); srcContext = main_source; includes = new Vector<SourceFile*>; includes->append (main_source); curr_inc = NULL; fragmented = 0; hwcprof = 0; hdrOffset = 0; hasDwarf = false; hasStabs = false; readStabs = false; comComs = NULL; infoList = NULL; datatypes = NULL; objStabs = NULL; disasm = NULL; comp_flags = NULL; comp_dir = NULL; linkerStabName = NULL; disMTime = (time_t) 0; stabsMTime = (time_t) 0; real_timestamp = 0; curr_timestamp = 0; src_items = NULL; dis_items = NULL; data_items = NULL; cur_dbev = NULL; maximum = NULL; maximum_inc = NULL; empty = NULL; inlinedSubr = NULL;} Module::~Module (){ removeStabsTmp (); delete includes; if (comComs != NULL) { comComs->destroy (); delete comComs; } free (comp_flags); free (comp_dir); free (linkerStabName); free (disPath); free (stabsPath); free (disName); free (stabsName); delete functions; free (file_name); if (indexStabsLink) // Remove a link to the current module indexStabsLink->indexStabsLink = NULL; if (dot_o_file) { delete dot_o_file->dbeFile; delete dot_o_file; } delete src_items; delete dis_items; delete disasm; free (inlinedSubr); if (lang_code != Sp_lang_java) delete dbeFile; } Stabs *Module::openDebugInfo (){ setFile (); objStabs = loadobject->openDebugInfo (); return objStabs;} voidModule::removeStabsTmp (){ // Remove temporary *.o (got from *.a) after reading Stabs if (stabsTmp != NULL) { unlink (stabsTmp); free (stabsTmp); stabsTmp = NULL; }} int64_tModule::get_size (){ Function *fp; int index; int64_t result = 0; Vec_loop (Function*, functions, index, fp) { result += fp->size; } return result;} boolModule::is_fortran (){ return Stabs::is_fortran (lang_code);} SourceFile *Module::findSource (const char *fname, bool create){ SourceFile *sf = NULL; if (loadobject && loadobject->firstExp) sf = loadobject->firstExp->get_source (fname); if (sf == NULL) sf = dbeSession->createSourceFile (fname); for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++) { SourceFile *sf1 = includes->fetch (i); if (sf == sf1) return sf; } if (create) { if (includes == NULL) includes = new Vector<SourceFile*>; includes->append (sf); return sf; } return NULL;} SourceFile *Module::setIncludeFile (char *includeFile){ curr_inc = NULL; if (includeFile) curr_inc = findSource (includeFile, true); return curr_inc;} char *Module::anno_str (char *fnm){ char timebuf1[26], timebuf2[26]; const time_t real_time = (time_t) (unsigned int) real_timestamp; const time_t curr_time = (time_t) (unsigned int) curr_timestamp; switch (status) { case AE_OK: case AE_NOTREAD: return NULL; case AE_NOSRC: return dbe_sprintf (GTXT ("Source file `%s' not readable"), fnm ? fnm : file_name); case AE_NOOBJ: if (lang_code == Sp_lang_java) { Emsg *emsg = get_error (); if (emsg) { char *s = dbe_strdup (emsg->get_msg ()); remove_msg (emsg); return s; } return dbe_sprintf (GTXT ("Object file `%s.class' not readable"), name); } return dbe_sprintf (GTXT ("Object file `%s' not readable"), get_name ()); case AE_NOLOBJ: if (lang_code == Sp_lang_java) return dbe_sprintf (GTXT ("Object file `%s' not readable"), dbeFile ? dbeFile->get_name () : name); return dbe_sprintf (GTXT ("Object file `%s' not readable"), loadobject->get_pathname ()); case AE_NOSTABS: return dbe_sprintf (GTXT ("Error reading line-number information in object `%s'; source annotation not available"), stabsPath ? stabsPath : NTXT ("")); case AE_NOSYMTAB: return dbe_sprintf (GTXT ("Error reading symbol table in object `%s'; disassembly annotation not available"), disPath ? disPath : NTXT ("")); case AE_TIMESRC: return dbe_sprintf (GTXT ("Warning! Source file `%s' is newer than the experiment data"), main_source->dbeFile->getResolvedPath ()); case AE_TIMEDIS: return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), disName ? disName : NTXT ("")); case AE_TIMESTABS: return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), stabsName ? stabsName : NTXT ("")); case AE_TIMESTABS_DIFF: snprintf (timebuf1, sizeof (timebuf1), NTXT ("%s"), ctime (&curr_time)); snprintf (timebuf2, sizeof (timebuf2), NTXT ("%s"), ctime (&real_time)); timebuf1[24] = timebuf2[24] = '\0'; return dbe_sprintf (GTXT ("Warning! Object file `%s' is not the same one that was linked into executable.\n" "\tObject file: `%s'\n\tcompiled on: %s\n" "\tExecutable contains object file compiled on: %s"), getResolvedObjectPath (), getResolvedObjectPath (), timebuf1, timebuf2); case AE_OTHER: default: return dbe_strdup (GTXT ("Annotation computation error")); }}//anno_str LoadObject *Module::createLoadObject (const char *lo_name){ LoadObject *lo = new LoadObject (lo_name); lo->dbeFile->filetype |= DbeFile::F_DOT_O; return lo;} static booltsIsNewer (time_t t1, time_t t2){ return t1 != 0 && t2 != 0 && t1 < t2;} Module::Anno_ErrorsModule::checkTimeStamp (bool chkDis){ /* Check the linked and the real object timestamps due to bug #4796329 */ if (real_timestamp && curr_timestamp && real_timestamp != curr_timestamp) return AE_TIMESTABS_DIFF; time_t srctime = main_source->getMTime (); for (int index = 0; index < dbeSession->nexps (); index++) { time_t mtime = dbeSession->get_exp (index)->get_mtime (); if (tsIsNewer (mtime, srctime)) return AE_TIMESRC; if (tsIsNewer (mtime, stabsMTime)) return AE_TIMESTABS; if (chkDis && tsIsNewer (mtime, disMTime)) return AE_TIMEDIS; } return AE_OK;}//checkTimeStamp static size_tget_ar_size (char *s, size_t len){ size_t sz = 0; for (size_t i = 0; i < len; i++) { if (s[i] < '0' || s[i] > '9') break; sz = sz * 10 + (s[i] - '0'); } return sz;} static voiddump_hdr_field (char *nm, char *s, size_t len){ Dprintf (DEBUG_READ_AR, NTXT (" %s "), nm); for (size_t i = 0; i < len; i++) Dprintf (DEBUG_READ_AR, "%c", isprint (s[i]) ? s[i] : '?'); Dprintf (DEBUG_READ_AR, NTXT (" ")); for (size_t i = 0; i < len; i++) Dprintf (DEBUG_READ_AR, NTXT (" %d"), s[i]); Dprintf (DEBUG_READ_AR, NTXT (" \n"));} static voiddump_ar_hdr (int lineNum, struct ar_hdr *hdr){ if (DEBUG_READ_AR) { Dprintf (DEBUG_READ_AR, NTXT ("Module::read_ar %d\n"), lineNum); dump_hdr_field (NTXT ("ar_name"), hdr->ar_name, sizeof (hdr->ar_name)); dump_hdr_field (NTXT ("ar_date"), hdr->ar_date, sizeof (hdr->ar_date)); dump_hdr_field (NTXT ("ar_uid"), hdr->ar_uid, sizeof (hdr->ar_uid)); dump_hdr_field (NTXT ("ar_gid"), hdr->ar_gid, sizeof (hdr->ar_gid)); dump_hdr_field (NTXT ("ar_mode"), hdr->ar_mode, sizeof (hdr->ar_mode)); dump_hdr_field (NTXT ("ar_size"), hdr->ar_size, sizeof (hdr->ar_size)); dump_hdr_field (NTXT ("ar_fmag"), hdr->ar_fmag, sizeof (hdr->ar_fmag)); }} boolModule::read_ar (int ar, int obj, char *obj_base){ struct ar_hdr hdr; // Archive header char magic[SARMAG]; // Magic string from archive Dprintf (DEBUG_READ_AR, "Module::read_ar %d %p %s %s \n", __LINE__, this, STR (obj_base), STR (get_name ())); // Check the magic string if ((read_from_file (ar, magic, SARMAG) != SARMAG) || strncmp (magic, ARMAG, SARMAG)) return false; // Read and skip the first file in the archive (index file to ld) if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) return false; DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), SEEK_CUR) == -1) return false; // Read the string file where it keeps long file names (if exist) if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) return false; DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); char *longnames = NULL; // Area with names longer than ~13 size_t longnames_size = 0; if (!strncmp (hdr.ar_name, NTXT ("//"), 2)) { longnames_size = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); longnames = (char *) xmalloc (longnames_size + 1); int64_t cnt = read_from_file (ar, longnames, longnames_size); if (cnt != (int64_t) longnames_size) { free (longnames); return false; } longnames[longnames_size] = 0; } else // back out, no long file names lseek (ar, -(sizeof (hdr)), SEEK_CUR); // Search the ar for the object file name char ar_buf[sizeof (hdr.ar_name) + 1]; ar_buf[sizeof (hdr.ar_name)] = 0; while (1) { if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) break; DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); char *ar_name; if (hdr.ar_name[0] != '/') { // Name is in the header for (size_t i = 0; i < sizeof (hdr.ar_name); i++) { if (hdr.ar_name[i] == '/') { ar_buf[i] = 0; break; } ar_buf[i] = hdr.ar_name[i]; } ar_name = ar_buf; } else if (hdr.ar_name[1] == ' ') { // Name is blank ar_buf[0] = 0; ar_name = ar_buf; } else { // Name is in the string table if (longnames == NULL) break; size_t offset = get_ar_size (hdr.ar_name + 1, sizeof (hdr.ar_name) - 1); if (offset >= longnames_size) break; for (size_t i = offset; i < longnames_size; i++) { if (longnames[i] == '/') { longnames[i] = 0; break; } } ar_name = longnames + offset; } Dprintf (DEBUG_READ_AR, "Module::read_ar %d ar_name=%s\n", __LINE__, ar_name); if (streq (ar_name, obj_base)) { // create object file free (longnames); for (size_t objsize = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); objsize > 0;) { char buf[MAXPATHLEN]; size_t n = objsize < sizeof (buf) ? objsize : sizeof (buf); int64_t cnt = read_from_file (ar, buf, n); if (cnt != (int64_t) n) return false; cnt = write (obj, buf, n); if (cnt != (int64_t) n) return false; objsize -= n; } return true; } if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), SEEK_CUR) == -1) break; } free (longnames); return false;} static char *get_obj_name_from_lib (char *nm){ char *base = strrchr (nm, '('); if (base) { size_t last = strlen (base) - 1; if (base[last] == ')') return base; } return NULL;} boolModule::setFile (){ if ((loadobject->flags & SEG_FLAG_DYNAMIC) != 0) return true; if ((loadobject->dbeFile->filetype & DbeFile::F_FICTION) != 0) return false; if ((flags & MOD_FLAG_UNKNOWN) != 0) return true; if (lang_code == Sp_lang_java) { if (dbeFile->get_need_refind ()) { char *fnm = dbeFile->get_location (); stabsPath = dbe_strdup (fnm); stabsName = dbe_strdup (fnm); disPath = dbe_strdup (fnm); disName = dbe_strdup (fnm); stabsMTime = dbeFile->sbuf.st_mtime; } return dbeFile->get_location () != NULL; } if (dbeFile == NULL) { char *objname = get_obj_name_from_lib (name); if (objname) { // in the format of libpath(obj)Lines 1–500 of 1840. Load more
/* Copyright (C) 2021-2026 Free Software Foundation, Inc. Contributed by Oracle. This file is part of GNU Binutils. This program 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 3, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include <unistd.h> #include <ar.h> #include <ctype.h> #include <sys/param.h> #include "util.h" #include "DbeSession.h" #include "Experiment.h" #include "DataObject.h" #include "Function.h" #include "DbeView.h" #include "MetricList.h" #include "Module.h" #include "ClassFile.h" #include "LoadObject.h" #include "Disasm.h" #include "CompCom.h" #include "Dwarf.h" #include "DbeFile.h" #include "PathTree.h" #include "Elf.h" Module::Module () { lang_code = Sp_lang_unknown; flags = 0; status = AE_NOTREAD; openSourceFlag = AE_NOTREAD; hexVisible = false; disPath = NULL; stabsPath = NULL; stabsTmp = NULL; disName = NULL; stabsName = NULL; indexStabsLink = NULL; file_name = NULL; functions = new Vector<Function*>; loadobject = NULL; dot_o_file = NULL; main_source = dbeSession->get_Unknown_Source (); srcContext = main_source; includes = new Vector<SourceFile*>; includes->append (main_source); curr_inc = NULL; fragmented = 0; hwcprof = 0; hdrOffset = 0; hasDwarf = false; hasStabs = false; readStabs = false; comComs = NULL; infoList = NULL; datatypes = NULL; objStabs = NULL; disasm = NULL; comp_flags = NULL; comp_dir = NULL; linkerStabName = NULL; disMTime = (time_t) 0; stabsMTime = (time_t) 0; real_timestamp = 0; curr_timestamp = 0; src_items = NULL; dis_items = NULL; data_items = NULL; cur_dbev = NULL; maximum = NULL; maximum_inc = NULL; empty = NULL; inlinedSubr = NULL; } Module::~Module () { removeStabsTmp (); delete includes; if (comComs != NULL) { comComs->destroy (); delete comComs; } free (comp_flags); free (comp_dir); free (linkerStabName); free (disPath); free (stabsPath); free (disName); free (stabsName); delete functions; free (file_name); if (indexStabsLink) // Remove a link to the current module indexStabsLink->indexStabsLink = NULL; if (dot_o_file) { delete dot_o_file->dbeFile; delete dot_o_file; } delete src_items; delete dis_items; delete disasm; free (inlinedSubr); if (lang_code != Sp_lang_java) delete dbeFile; } Stabs * Module::openDebugInfo () { setFile (); objStabs = loadobject->openDebugInfo (); return objStabs; } void Module::removeStabsTmp () { // Remove temporary *.o (got from *.a) after reading Stabs if (stabsTmp != NULL) { unlink (stabsTmp); free (stabsTmp); stabsTmp = NULL; } } int64_t Module::get_size () { Function *fp; int index; int64_t result = 0; Vec_loop (Function*, functions, index, fp) { result += fp->size; } return result; } bool Module::is_fortran () { return Stabs::is_fortran (lang_code); } SourceFile * Module::findSource (const char *fname, bool create) { SourceFile *sf = NULL; if (loadobject && loadobject->firstExp) sf = loadobject->firstExp->get_source (fname); if (sf == NULL) sf = dbeSession->createSourceFile (fname); for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++) { SourceFile *sf1 = includes->fetch (i); if (sf == sf1) return sf; } if (create) { if (includes == NULL) includes = new Vector<SourceFile*>; includes->append (sf); return sf; } return NULL; } SourceFile * Module::setIncludeFile (char *includeFile) { curr_inc = NULL; if (includeFile) curr_inc = findSource (includeFile, true); return curr_inc; } char * Module::anno_str (char *fnm) { char timebuf1[26], timebuf2[26]; const time_t real_time = (time_t) (unsigned int) real_timestamp; const time_t curr_time = (time_t) (unsigned int) curr_timestamp; switch (status) { case AE_OK: case AE_NOTREAD: return NULL; case AE_NOSRC: return dbe_sprintf (GTXT ("Source file `%s' not readable"), fnm ? fnm : file_name); case AE_NOOBJ: if (lang_code == Sp_lang_java) { Emsg *emsg = get_error (); if (emsg) { char *s = dbe_strdup (emsg->get_msg ()); remove_msg (emsg); return s; } return dbe_sprintf (GTXT ("Object file `%s.class' not readable"), name); } return dbe_sprintf (GTXT ("Object file `%s' not readable"), get_name ()); case AE_NOLOBJ: if (lang_code == Sp_lang_java) return dbe_sprintf (GTXT ("Object file `%s' not readable"), dbeFile ? dbeFile->get_name () : name); return dbe_sprintf (GTXT ("Object file `%s' not readable"), loadobject->get_pathname ()); case AE_NOSTABS: return dbe_sprintf (GTXT ("Error reading line-number information in object `%s'; source annotation not available"), stabsPath ? stabsPath : NTXT ("")); case AE_NOSYMTAB: return dbe_sprintf (GTXT ("Error reading symbol table in object `%s'; disassembly annotation not available"), disPath ? disPath : NTXT ("")); case AE_TIMESRC: return dbe_sprintf (GTXT ("Warning! Source file `%s' is newer than the experiment data"), main_source->dbeFile->getResolvedPath ()); case AE_TIMEDIS: return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), disName ? disName : NTXT ("")); case AE_TIMESTABS: return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), stabsName ? stabsName : NTXT ("")); case AE_TIMESTABS_DIFF: snprintf (timebuf1, sizeof (timebuf1), NTXT ("%s"), ctime (&curr_time)); snprintf (timebuf2, sizeof (timebuf2), NTXT ("%s"), ctime (&real_time)); timebuf1[24] = timebuf2[24] = '\0'; return dbe_sprintf (GTXT ("Warning! Object file `%s' is not the same one that was linked into executable.\n" "\tObject file: `%s'\n\tcompiled on: %s\n" "\tExecutable contains object file compiled on: %s"), getResolvedObjectPath (), getResolvedObjectPath (), timebuf1, timebuf2); case AE_OTHER: default: return dbe_strdup (GTXT ("Annotation computation error")); } }//anno_str LoadObject * Module::createLoadObject (const char *lo_name) { LoadObject *lo = new LoadObject (lo_name); lo->dbeFile->filetype |= DbeFile::F_DOT_O; return lo; } static bool tsIsNewer (time_t t1, time_t t2) { return t1 != 0 && t2 != 0 && t1 < t2; } Module::Anno_Errors Module::checkTimeStamp (bool chkDis) { /* Check the linked and the real object timestamps due to bug #4796329 */ if (real_timestamp && curr_timestamp && real_timestamp != curr_timestamp) return AE_TIMESTABS_DIFF; time_t srctime = main_source->getMTime (); for (int index = 0; index < dbeSession->nexps (); index++) { time_t mtime = dbeSession->get_exp (index)->get_mtime (); if (tsIsNewer (mtime, srctime)) return AE_TIMESRC; if (tsIsNewer (mtime, stabsMTime)) return AE_TIMESTABS; if (chkDis && tsIsNewer (mtime, disMTime)) return AE_TIMEDIS; } return AE_OK; }//checkTimeStamp static size_t get_ar_size (char *s, size_t len) { size_t sz = 0; for (size_t i = 0; i < len; i++) { if (s[i] < '0' || s[i] > '9') break; sz = sz * 10 + (s[i] - '0'); } return sz; } static void dump_hdr_field (char *nm, char *s, size_t len) { Dprintf (DEBUG_READ_AR, NTXT (" %s "), nm); for (size_t i = 0; i < len; i++) Dprintf (DEBUG_READ_AR, "%c", isprint (s[i]) ? s[i] : '?'); Dprintf (DEBUG_READ_AR, NTXT (" ")); for (size_t i = 0; i < len; i++) Dprintf (DEBUG_READ_AR, NTXT (" %d"), s[i]); Dprintf (DEBUG_READ_AR, NTXT (" \n")); } static void dump_ar_hdr (int lineNum, struct ar_hdr *hdr) { if (DEBUG_READ_AR) { Dprintf (DEBUG_READ_AR, NTXT ("Module::read_ar %d\n"), lineNum); dump_hdr_field (NTXT ("ar_name"), hdr->ar_name, sizeof (hdr->ar_name)); dump_hdr_field (NTXT ("ar_date"), hdr->ar_date, sizeof (hdr->ar_date)); dump_hdr_field (NTXT ("ar_uid"), hdr->ar_uid, sizeof (hdr->ar_uid)); dump_hdr_field (NTXT ("ar_gid"), hdr->ar_gid, sizeof (hdr->ar_gid)); dump_hdr_field (NTXT ("ar_mode"), hdr->ar_mode, sizeof (hdr->ar_mode)); dump_hdr_field (NTXT ("ar_size"), hdr->ar_size, sizeof (hdr->ar_size)); dump_hdr_field (NTXT ("ar_fmag"), hdr->ar_fmag, sizeof (hdr->ar_fmag)); } } bool Module::read_ar (int ar, int obj, char *obj_base) { struct ar_hdr hdr; // Archive header char magic[SARMAG]; // Magic string from archive Dprintf (DEBUG_READ_AR, "Module::read_ar %d %p %s %s \n", __LINE__, this, STR (obj_base), STR (get_name ())); // Check the magic string if ((read_from_file (ar, magic, SARMAG) != SARMAG) || strncmp (magic, ARMAG, SARMAG)) return false; // Read and skip the first file in the archive (index file to ld) if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) return false; DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), SEEK_CUR) == -1) return false; // Read the string file where it keeps long file names (if exist) if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) return false; DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); char *longnames = NULL; // Area with names longer than ~13 size_t longnames_size = 0; if (!strncmp (hdr.ar_name, NTXT ("//"), 2)) { longnames_size = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); longnames = (char *) xmalloc (longnames_size + 1); int64_t cnt = read_from_file (ar, longnames, longnames_size); if (cnt != (int64_t) longnames_size) { free (longnames); return false; } longnames[longnames_size] = 0; } else // back out, no long file names lseek (ar, -(sizeof (hdr)), SEEK_CUR); // Search the ar for the object file name char ar_buf[sizeof (hdr.ar_name) + 1]; ar_buf[sizeof (hdr.ar_name)] = 0; while (1) { if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) break; DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); char *ar_name; if (hdr.ar_name[0] != '/') { // Name is in the header for (size_t i = 0; i < sizeof (hdr.ar_name); i++) { if (hdr.ar_name[i] == '/') { ar_buf[i] = 0; break; } ar_buf[i] = hdr.ar_name[i]; } ar_name = ar_buf; } else if (hdr.ar_name[1] == ' ') { // Name is blank ar_buf[0] = 0; ar_name = ar_buf; } else { // Name is in the string table if (longnames == NULL) break; size_t offset = get_ar_size (hdr.ar_name + 1, sizeof (hdr.ar_name) - 1); if (offset >= longnames_size) break; for (size_t i = offset; i < longnames_size; i++) { if (longnames[i] == '/') { longnames[i] = 0; break; } } ar_name = longnames + offset; } Dprintf (DEBUG_READ_AR, "Module::read_ar %d ar_name=%s\n", __LINE__, ar_name); if (streq (ar_name, obj_base)) { // create object file free (longnames); for (size_t objsize = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); objsize > 0;) { char buf[MAXPATHLEN]; size_t n = objsize < sizeof (buf) ? objsize : sizeof (buf); int64_t cnt = read_from_file (ar, buf, n); if (cnt != (int64_t) n) return false; cnt = write (obj, buf, n); if (cnt != (int64_t) n) return false; objsize -= n; } return true; } if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), SEEK_CUR) == -1) break; } free (longnames); return false; } static char * get_obj_name_from_lib (char *nm) { char *base = strrchr (nm, '('); if (base) { size_t last = strlen (base) - 1; if (base[last] == ')') return base; } return NULL; } bool Module::setFile () { if ((loadobject->flags & SEG_FLAG_DYNAMIC) != 0) return true; if ((loadobject->dbeFile->filetype & DbeFile::F_FICTION) != 0) return false; if ((flags & MOD_FLAG_UNKNOWN) != 0) return true; if (lang_code == Sp_lang_java) { if (dbeFile->get_need_refind ()) { char *fnm = dbeFile->get_location (); stabsPath = dbe_strdup (fnm); stabsName = dbe_strdup (fnm); disPath = dbe_strdup (fnm); disName = dbe_strdup (fnm); stabsMTime = dbeFile->sbuf.st_mtime; } return dbeFile->get_location () != NULL; } if (dbeFile == NULL) { char *objname = get_obj_name_from_lib (name); if (objname) { // in the format of libpath(obj)