/* Copyright (C) 2021-2023 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 #include "util.h" #include "StringBuilder.h" #include "Application.h" #include "DbeSession.h" #include "Experiment.h" #include "Exp_Layout.h" #include "DataObject.h" #include "Elf.h" #include "Function.h" #include "Module.h" #include "ClassFile.h" #include "Stabs.h" #include "LoadObject.h" #include "dbe_types.h" #include "DbeFile.h" #include "ExpGroup.h" enum { LO_InstHTableSize = 4096, HTableSize = 1024 }; LoadObject * LoadObject::create_item (const char *nm, int64_t chksum) { LoadObject *lo = new LoadObject (nm); lo->checksum = chksum; dbeSession->append (lo); return lo; } LoadObject * LoadObject::create_item (const char *nm, const char *_runTimePath, DbeFile *df) { LoadObject *lo = new LoadObject (nm); lo->runTimePath = dbe_strdup (_runTimePath); lo->dbeFile->orig_location = dbe_strdup (_runTimePath); if (df) { if ((df->filetype & DbeFile::F_JAR_FILE) != 0) { if (lo->dbeFile->find_in_jar_file (nm, df->get_jar_file ())) { lo->dbeFile->inArchive = df->inArchive; lo->dbeFile->container = df; } } else { lo->dbeFile->set_location (df->get_location ()); lo->dbeFile->sbuf = df->sbuf; lo->dbeFile->inArchive = df->inArchive; } } dbeSession->append (lo); return lo; } LoadObject::LoadObject (const char *loname) { flags = 0; size = 0; type = SEG_UNKNOWN; isReadStabs = false; need_swap_endian = false; instHTable = new DbeInstr*[LO_InstHTableSize]; for (int i = 0; i < LO_InstHTableSize; i++) instHTable[i] = NULL; functions = new Vector; funcHTable = new Function*[HTableSize]; for (int i = 0; i < HTableSize; i++) funcHTable[i] = NULL; seg_modules = new Vector; modules = new HashMap; platform = Unknown; noname = dbeSession->createUnknownModule (this); modules->put (noname->get_name (), noname); pathname = NULL; arch_name = NULL; runTimePath = NULL; objStabs = NULL; firstExp = NULL; seg_modules_map = NULL; comp_funcs = NULL; warnq = new Emsgqueue (NTXT ("lo_warnq")); commentq = new Emsgqueue (NTXT ("lo_commentq")); elf_lo = NULL; elf_inited = false; checksum = 0; isUsed = false; h_function = NULL; h_instr = NULL; char *nm = (char *) loname; if (strncmp (nm, NTXT ("./"), 2) == 0) nm += 2; set_name (nm); dbeFile = new DbeFile (nm); dbeFile->filetype |= DbeFile::F_LOADOBJ | DbeFile::F_FILE; } LoadObject::~LoadObject () { delete seg_modules_map; delete functions; delete[] instHTable; delete[] funcHTable; delete seg_modules; delete modules; delete elf_lo; free (pathname); free (arch_name); free (runTimePath); delete objStabs; delete warnq; delete commentq; delete h_instr; } Elf * LoadObject::get_elf () { if (elf_lo == NULL) { if (dbeFile->get_need_refind ()) elf_inited = false; if (elf_inited) return NULL; elf_inited = true; char *fnm = dbeFile->get_location (); if (fnm == NULL) { append_msg (CMSG_ERROR, GTXT ("Cannot find file: `%s'"), dbeFile->get_name ()); return NULL; } Elf::Elf_status st = Elf::ELF_ERR_CANT_OPEN_FILE; elf_lo = Elf::elf_begin (fnm, &st); if (elf_lo == NULL) switch (st) { case Elf::ELF_ERR_CANT_OPEN_FILE: append_msg (CMSG_ERROR, GTXT ("Cannot open ELF file `%s'"), fnm); break; case Elf::ELF_ERR_BAD_ELF_FORMAT: default: append_msg (CMSG_ERROR, GTXT ("Cannot read ELF header of `%s'"), fnm); break; } } return elf_lo; } Stabs * LoadObject::openDebugInfo (char *fname, Stabs::Stab_status *stp) { if (objStabs == NULL) { if (fname == NULL) return NULL; objStabs = new Stabs (fname, get_pathname ()); Stabs::Stab_status st = objStabs->get_status (); if ((st == Stabs::DBGD_ERR_NONE) && (checksum != 0)) { Elf *elf = get_elf (); if (elf && (checksum != elf->elf_checksum ())) { char *buf = dbe_sprintf (GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"), fname); commentq->append (new Emsg (CMSG_ERROR, buf)); delete buf; st = Stabs::DBGD_ERR_CHK_SUM; } } if (stp) *stp = st; if (st != Stabs::DBGD_ERR_NONE) { delete objStabs; objStabs = NULL; } } return objStabs; } uint64_t LoadObject::get_addr () { return MAKE_ADDRESS (seg_idx, 0); } bool LoadObject::compare (const char *_path, int64_t _checksum) { return _checksum == checksum && dbe_strcmp (_path, get_pathname ()) == 0; } int LoadObject::compare (const char *_path, const char *_runTimePath, DbeFile *df) { int ret = 0; if (dbe_strcmp (_path, get_pathname ()) != 0) return ret; ret |= CMP_PATH; if (_runTimePath) { if (dbe_strcmp (_runTimePath, runTimePath) != 0) return ret; ret |= CMP_RUNTIMEPATH; } if (df && dbeFile->compare (df)) ret |= CMP_CHKSUM; return ret; } void LoadObject::set_platform (Platform_t pltf, int wsz) { switch (pltf) { case Sparc: case Sparcv9: case Sparcv8plus: platform = (wsz == W64) ? Sparcv9 : Sparc; break; case Intel: case Amd64: platform = (wsz == W64) ? Amd64 : Intel; break; default: platform = pltf; break; } }; void LoadObject::set_name (char *string) { char *p; pathname = dbe_strdup (string); p = get_basename (pathname); if (p[0] == '<') name = dbe_strdup (p); else // set a short name to "" name = dbe_sprintf (NTXT ("<%s>"), p); } void LoadObject::dump_functions (FILE *out) { int index; Function *fitem; char *sname, *mname; if (platform == Java) { JMethod *jmthd; Vector *jmethods = (Vector*)functions; Vec_loop (JMethod*, jmethods, index, jmthd) { fprintf (out, "id %6llu, @0x%llx sz-%lld %s (module = %s)\n", (unsigned long long) jmthd->id, (long long) jmthd->get_mid (), (long long) jmthd->size, jmthd->get_name (), jmthd->module ? jmthd->module->file_name : noname->file_name); } } else { Vec_loop (Function*, functions, index, fitem) { if (fitem->alias && fitem->alias != fitem) fprintf (out, "id %6llu, @0x%llx - %s == alias of '%s'\n", (ull_t) fitem->id, (ull_t) fitem->img_offset, fitem->get_name (), fitem->alias->get_name ()); else { mname = fitem->module ? fitem->module->file_name : noname->file_name; sname = fitem->getDefSrcName (); fprintf (out, "id %6llu, @0x%llx - 0x%llx [save 0x%llx] o-%lld sz-%lld %s (module = %s)", (ull_t) fitem->id, (ull_t) fitem->img_offset, (ull_t) (fitem->img_offset + fitem->size), (ull_t) fitem->save_addr, (ull_t) fitem->img_offset, (ll_t) fitem->size, fitem->get_name (), mname); if (sname && !streq (sname, mname)) fprintf (out, " (Source = %s)", sname); fprintf (out, "\n"); } } } } int LoadObject::get_index (Function *func) { Function *fp; uint64_t offset; int x; int left = 0; int right = functions->size () - 1; offset = func->img_offset; while (left <= right) { x = (left + right) / 2; fp = functions->fetch (x); if (left == right) { if (offset >= fp->img_offset + fp->size) return -1; if (offset >= fp->img_offset) return x; return -1; } if (offset < fp->img_offset) right = x - 1; else if (offset >= fp->img_offset + fp->size) left = x + 1; else return x; } return -1; } char * LoadObject::get_alias (Function *func) { Function *fp, *alias; int index, nsize; static char buf[1024]; if (func->img_offset == 0 || func->alias == NULL) return NULL; int fid = get_index (func); if (fid == -1) return NULL; nsize = functions->size (); alias = func->alias; for (index = fid; index < nsize; index++) { fp = functions->fetch (index); if (fp->alias != alias) { fid = index; break; } } *buf = '\0'; for (index--; index >= 0; index--) { fp = functions->fetch (index); if (fp->alias != alias) break; if (fp != alias) { size_t len = strlen (buf); if (*buf != '\0') { snprintf (buf + len, sizeof (buf) - len, NTXT (", ")); len = strlen (buf); } snprintf (buf + len, sizeof (buf) - len, "%s", fp->get_name ()); } } return buf; } DbeInstr* LoadObject::find_dbeinstr (uint64_t file_off) { int hash = (((int) file_off) >> 2) & (LO_InstHTableSize - 1); DbeInstr *instr = instHTable[hash]; if (instr && instr->img_offset == file_off) return instr; Function *fp = find_function (file_off); if (fp == NULL) fp = dbeSession->get_Unknown_Function (); uint64_t func_off = file_off - fp->img_offset; instr = fp->find_dbeinstr (0, func_off); instHTable[hash] = instr; return instr; } Function * LoadObject::find_function (uint64_t foff) { // Look up in the hash table int hash = (((int) foff) >> 6) & (HTableSize - 1); Function *func = funcHTable[hash]; if (func && foff >= func->img_offset && foff < func->img_offset + func->size) return func->alias ? func->alias : func; // Use binary search func = NULL; int left = 0; int right = functions->size () - 1; while (left <= right) { int x = (left + right) / 2; Function *fp = functions->fetch (x); assert (fp != NULL); if (foff < fp->img_offset) right = x - 1; else if (foff >= fp->img_offset + fp->size) left = x + 1; else { func = fp; break; } } // Plug the hole with a static function char *func_name = NULL; Size low_bound = 0, high_bound = 0; if (func == NULL) { int last = functions->size () - 1; uint64_t usize = (uint64_t) size; if (foff >= usize) { // Cannot map to this LoadObject. Probably LoadObject was changed. if (last >= 0 && functions->fetch (last)->img_offset == usize) { // Function is already created func = functions->fetch (last); if (func->size < 0 || (uint64_t) func->size < foff - usize) func->size = foff - usize; } else { low_bound = size; high_bound = foff; func_name = dbe_sprintf (GTXT ("@0x%llx (%s) -- no functions found"), low_bound, name); } } else if (last < 0) { low_bound = 0; high_bound = size; func_name = dbe_sprintf (GTXT ("@0x%llx (%s) -- no functions found"), low_bound, name); } else if (foff < functions->fetch (0)->img_offset) { low_bound = 0; high_bound = functions->fetch (0)->img_offset; } else { Function *fp = functions->fetch (last); if (foff >= fp->img_offset + fp->size) { low_bound = fp->img_offset + fp->size; high_bound = size; } else { fp = functions->fetch (left); if (foff >= fp->img_offset + fp->size) { low_bound = fp->img_offset + fp->size; high_bound = functions->fetch (left + 1)->img_offset; } else { Function *fp1 = functions->fetch (left - 1); low_bound = fp1->img_offset + fp1->size; high_bound = fp->img_offset; } } } } if (func == NULL) { func = dbeSession->createFunction (); func->size = (unsigned) (high_bound - low_bound); func->module = noname; func->img_fname = get_pathname (); func->img_offset = (off_t) low_bound; noname->functions->append (func); // unordered if (func_name == NULL) func_name = dbe_sprintf (GTXT ("@0x%llx (%s)"), low_bound, name); func->set_name (func_name); free (func_name); // now insert the function functions->insert (left, func); } // Update the hash table funcHTable[hash] = func; return func->alias ? func->alias : func; } static void fixFuncAlias (Vector *SymLst) { int ind, i, k; int64_t len, bestLen, maxSize; Function *sym, *bestAlias; // XXXX it is a clone of Stabs::fixSymtabAlias() ind = SymLst->size () - 1; for (i = 0; i < ind; i++) { bestAlias = SymLst->fetch (i); if (bestAlias->img_offset == 0) // Ignore this bad symbol continue; sym = SymLst->fetch (i + 1); if (bestAlias->img_offset != sym->img_offset) { if (bestAlias->size == 0 || sym->img_offset < bestAlias->img_offset + bestAlias->size) bestAlias->size = (int) (sym->img_offset - bestAlias->img_offset); continue; } // Find a "best" alias bestLen = strlen (bestAlias->get_name ()); maxSize = bestAlias->size; for (k = i + 1; k <= ind; k++) { sym = SymLst->fetch (k); if (bestAlias->img_offset != sym->img_offset) { // no more aliases if ((maxSize == 0) || (sym->img_offset < bestAlias->img_offset + maxSize)) maxSize = sym->img_offset - bestAlias->img_offset; break; } if (maxSize < sym->size) maxSize = sym->size; len = strlen (sym->get_name ()); if (len < bestLen) { bestAlias = sym; bestLen = len; } } for (; i < k; i++) { sym = SymLst->fetch (i); sym->alias = bestAlias; sym->size = maxSize; } i--; } } void LoadObject::post_process_functions () { if (flags & SEG_FLAG_DYNAMIC || platform == Java) return; char *msg = GTXT ("Processing Load Object Data"); if (dbeSession->is_interactive ()) theApplication->set_progress (1, msg); // First sort the functions functions->sort (func_compare); fixFuncAlias (functions); Module *mitem; int index; Vec_loop (Module*, seg_modules, index, mitem) { mitem->functions->sort (func_compare); } // Find any derived functions, and set their derivedNode Function *fitem; Vec_loop (Function*, functions, index, fitem) { if (dbeSession->is_interactive () && index % 5000 == 0) { int percent = (int) (100.0 * index / functions->size ()); theApplication->set_progress (percent, (percent != 0) ? NULL : msg); } fitem->findDerivedFunctions (); } // 4987698: get the alias name for MAIN_ fitem = find_function (NTXT ("MAIN_")); if (fitem) fitem->module->read_stabs (); fitem = find_function (NTXT ("@plt")); if (fitem) fitem->flags |= FUNC_FLAG_PLT; if (dbeSession->is_interactive ()) theApplication->set_progress (0, NTXT ("")); } int LoadObject::func_compare (const void *p1, const void *p2) { Function *f1 = *(Function **) p1; Function *f2 = *(Function **) p2; if (f1->img_offset != f2->img_offset) return f1->img_offset > f2->img_offset ? 1 : -1; // annotated source not available for weak symbols. if ((f1->module->flags & MOD_FLAG_UNKNOWN) != 0) { if ((f2->module->flags & MOD_FLAG_UNKNOWN) == 0) return -1; } else if ((f2->module->flags & MOD_FLAG_UNKNOWN) != 0) return 1; return strcoll (f1->get_name (), f2->get_name ()); } Function * LoadObject::find_function (char *fname) { Function *fitem; int index; Vec_loop (Function*, functions, index, fitem) { if (strcmp (fitem->get_name (), fname) == 0) return fitem; } return (Function *) NULL; } Function * LoadObject::find_function (char *fname, unsigned int chksum) { Function *fitem; int index; Vec_loop (Function*, functions, index, fitem) { if (fitem->chksum == chksum && strcmp (fitem->get_name (), fname) == 0) return fitem; } return (Function *) NULL; } Module * LoadObject::find_module (char *mname) { for (int i = 0, sz = seg_modules ? seg_modules->size () : 0; i < sz; i++) { Module *module = seg_modules->fetch (i); if (strcmp (module->get_name (), mname) == 0) return module; } return (Module *) NULL; } LoadObject::Arch_status LoadObject::sync_read_stabs () { Arch_status st = ARCHIVE_SUCCESS; if (!isReadStabs) { aquireLock (); if (!isReadStabs) { st = read_stabs (); post_process_functions (); isReadStabs = true; } releaseLock (); } return st; } LoadObject::Arch_status LoadObject::read_stabs () { if ((dbeFile->filetype & DbeFile::F_FICTION) != 0) return ARCHIVE_SUCCESS; Arch_status stabs_status = ARCHIVE_ERR_OPEN; if (platform == Java) { Module *cf = NULL; for (int i = 0, sz = seg_modules ? seg_modules->size () : 0; i < sz; i++) { Module *mod = seg_modules->fetch (i); if (mod->dbeFile && (mod->dbeFile->filetype & DbeFile::F_JAVACLASS) != 0) { cf = mod; break; } } if (cf) { int status = cf->readFile (); switch (status) { case Module::AE_OK: stabs_status = ARCHIVE_SUCCESS; break; case Module::AE_NOSTABS: stabs_status = ARCHIVE_NO_STABS; break; case Module::AE_NOTREAD: default: stabs_status = ARCHIVE_ERR_OPEN; break; } } } else if (strchr (pathname, '`')) return ARCHIVE_SUCCESS; else { Arch_status st = ARCHIVE_WRONG_ARCH; Elf *elf = get_elf (); if (elf == NULL) { if (read_archive () == 0) st = ARCHIVE_SUCCESS; else { char *msg = dbe_sprintf (GTXT ("*** Warning: Can't open file: %s"), dbeFile->get_name ()); warnq->append (new Emsg (CMSG_ERROR, msg)); delete msg; } } else if (checksum != 0 && checksum != elf->elf_checksum ()) { if (read_archive () == 0) st = ARCHIVE_SUCCESS; else { char *msg = dbe_sprintf ( GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"), dbeFile->get_location ()); commentq->append (new Emsg (CMSG_ERROR, msg)); delete msg; } } if (st == ARCHIVE_SUCCESS) // An old archive is used return st; Stabs::Stab_status status = Stabs::DBGD_ERR_CANT_OPEN_FILE; char *location = dbeFile->get_location (true); if (location == NULL) return ARCHIVE_ERR_OPEN; if (openDebugInfo (location, &status)) { status = objStabs->read_archive (this); isRelocatable = objStabs->is_relocatable (); size = objStabs->get_textsz (); platform = objStabs->get_platform (); wsize = objStabs->get_class (); } switch (status) { case Stabs::DBGD_ERR_NONE: stabs_status = ARCHIVE_SUCCESS; break; case Stabs::DBGD_ERR_CANT_OPEN_FILE: stabs_status = ARCHIVE_ERR_OPEN; break; case Stabs::DBGD_ERR_BAD_ELF_LIB: case Stabs::DBGD_ERR_BAD_ELF_FORMAT: stabs_status = ARCHIVE_BAD_STABS; break; case Stabs::DBGD_ERR_NO_STABS: stabs_status = ARCHIVE_NO_STABS; break; case Stabs::DBGD_ERR_NO_DWARF: stabs_status = ARCHIVE_NO_DWARF; break; default: stabs_status = ARCHIVE_BAD_STABS; break; } } return stabs_status; } #define ARCH_STRLEN(s) ((strlen(s) + 4) & ~0x3 ) static int offsetCmp (const void *a, const void *b) { uint32_t o1 = ((inst_info_t *) a)->offset; uint32_t o2 = ((inst_info_t *) b)->offset; return o1 == o2 ? 0 : (o1 < o2 ? -1 : 1); } int LoadObject::read_archive () { if (arch_name == NULL) return 1; Module *mod = NULL; Function *func = NULL; char *buf; Data_window *dwin = new Data_window (arch_name); if (dwin->not_opened ()) { delete dwin; buf = dbe_sprintf (GTXT ("*** Warning: Error opening file for reading: %s: %s"), arch_name, strerror (errno)); warnq->append (new Emsg (CMSG_ERROR, buf)); delete buf; return 1; } dwin->need_swap_endian = need_swap_endian; // Prevent reading earlier archive files, which didn't support versioning. int64_t offset = 0; ARCH_common *cpkt = (ARCH_common*) dwin->bind (offset, sizeof (ARCH_common)); uint16_t v16; if (cpkt) { v16 = (uint16_t) cpkt->type; if (dwin->decode (v16) != ARCH_SEGMENT) cpkt = NULL; } if (cpkt == NULL) { buf = dbe_sprintf (GTXT ("archive file malformed %s"), arch_name); warnq->append (new Emsg (CMSG_WARN, buf)); delete buf; return 1; } char *msg = NULL; unsigned long long pointer_invalid = 0; for (int64_t last_offset = -5000;;) { cpkt = (ARCH_common*) dwin->bind (offset, sizeof (ARCH_common)); if (cpkt == NULL) break; v16 = (uint16_t) cpkt->size; uint32_t cpktsize = dwin->decode (v16); cpkt = (ARCH_common*) dwin->bind (offset, cpktsize); if ((cpkt == NULL) || (cpktsize == 0)) { buf = dbe_sprintf (GTXT ("archive file malformed %s"), arch_name); warnq->append (new Emsg (CMSG_WARN, buf)); delete buf; break; } // Update the progress bar if (dbeSession->is_interactive () && ((offset - last_offset) >= 5000)) { last_offset = offset; int percent = (int) (100.0 * offset / dwin->get_fsize ()); if (msg == NULL) msg = dbe_sprintf (GTXT ("Reading Load Object Data: %s"), name); theApplication->set_progress (percent, (percent != 0) ? NULL : msg); } char *ptr = (char *) cpkt; v16 = (uint16_t) cpkt->type; switch (dwin->decode (v16)) { case ARCH_SEGMENT: { ARCH_segment *aseg = (ARCH_segment*) cpkt; if (dwin->decode (aseg->version) != ARCH_VERSION) { buf = dbe_sprintf (GTXT ("Archive file version mismatch for %s"), arch_name); warnq->append (new Emsg (CMSG_ERROR, buf)); delete buf; if (dbeSession->is_interactive ()) theApplication->set_progress (0, ""); return 1; } if (size == 0) size = dwin->decode (aseg->textsz); Platform_t pltf = (Platform_t) dwin->decode (aseg->platform); if (pltf != Unknown) { platform = pltf; // override if known wsize = (platform == Sparcv9 || platform == Amd64) ? W64 : W32; } break; } case ARCH_MSG: { ARCH_message *amsg = (ARCH_message*) cpkt; buf = status_str ((Arch_status) dwin->decode (amsg->errcode)); commentq->append (new Emsg (CMSG_ARCHIVE, buf)); free (buf); break; } case ARCH_INF: { ARCH_info *ainf = (ARCH_info*) cpkt; Emsg *m = new Emsg (CMSG_ARCHIVE, (char*) (ainf + 1)); commentq->append (m); break; } case ARCH_MODULE: { ARCH_module *amod = (ARCH_module*) cpkt; char *str = ((char*) amod) + sizeof (ARCH_module); if (streq (str, SP_UNKNOWN_NAME) && streq (str + ARCH_STRLEN (str), SP_UNKNOWN_NAME)) { mod = noname; break; } mod = dbeSession->createModule (this, str); mod->lang_code = (Sp_lang_code) dwin->decode (amod->lang_code); mod->fragmented = dwin->decode (amod->fragmented); str += ARCH_STRLEN (str); mod->set_file_name (dbe_strdup (str)); modules->put (get_basename (str), mod); break; } case ARCH_FUNCTION: { if (mod == NULL) break; ARCH_function *afnc = (ARCH_function*) cpkt; func = dbeSession->createFunction (); func->img_offset = dwin->decode (afnc->offset); func->size = dwin->decode (afnc->size); func->save_addr = dwin->decode (afnc->save_addr) - dwin->decode (afnc->offset); func->module = mod; func->set_name (((char*) afnc) + sizeof (ARCH_function)); mod->functions->append (func); functions->append (func); break; } case ARCH_LDINSTR: if (mod == NULL) break; Dprintf (DEBUG_LOADOBJ, "LDINSTR list for %s\n", mod->get_name ()); if (mod->infoList == NULL) mod->infoList = new Vector; for (memop_info_t *mp = (memop_info_t*) (ptr + sizeof (ARCH_aninfo)); (char*) mp < ptr + cpktsize; mp++) { memop_info_t *memop = new memop_info_t; memop->offset = dwin->decode (mp->offset); memop->id = dwin->decode (mp->id); memop->signature = dwin->decode (mp->signature); memop->datatype_id = dwin->decode (mp->datatype_id); mod->ldMemops.append (memop); inst_info_t *instop = new inst_info_t; instop->type = CPF_INSTR_TYPE_LD; instop->offset = memop->offset; instop->memop = memop; mod->infoList->incorporate (instop, offsetCmp); Dprintf (DEBUG_LOADOBJ, "ld: offset=0x%04x id=0x%08x sig=0x%08x dtid=0x%08x\n", memop->offset, memop->id, memop->signature, memop->datatype_id); } Dprintf (DEBUG_LOADOBJ, "LDINSTR list of %lld for %s\n", (long long) mod->ldMemops.size (), mod->get_name ()); break; case ARCH_STINSTR: if (mod == NULL) break; Dprintf (DEBUG_LOADOBJ, NTXT ("STINSTR list for %s\n"), mod->get_name ()); if (mod->infoList == NULL) mod->infoList = new Vector; for (memop_info_t *mp = (memop_info_t*) (ptr + sizeof (ARCH_aninfo)); ((char *) mp) < ptr + cpktsize; mp++) { memop_info_t *memop = new memop_info_t; memop->offset = dwin->decode (mp->offset); memop->id = dwin->decode (mp->id); memop->signature = dwin->decode (mp->signature); memop->datatype_id = dwin->decode (mp->datatype_id); mod->stMemops.append (memop); inst_info_t *instop = new inst_info_t; instop->type = CPF_INSTR_TYPE_ST; instop->offset = memop->offset; instop->memop = memop; mod->infoList->incorporate (instop, offsetCmp); Dprintf (DEBUG_LOADOBJ, "st: offset=0x%04x id=0x%08x sig=0x%08x dtid=0x%08x\n", memop->offset, memop->id, memop->signature, memop->datatype_id); } Dprintf (DEBUG_LOADOBJ, "STINSTR list of %lld for %s\n", (long long) mod->stMemops.size (), mod->get_name ()); break; case ARCH_PREFETCH: if (mod == NULL) break; Dprintf (DEBUG_LOADOBJ, "PFINSTR list for %s\n", mod->get_name ()); if (mod->infoList == NULL) mod->infoList = new Vector; for (memop_info_t *mp = (memop_info_t*) (ptr + sizeof (ARCH_aninfo)); ((char*) mp) < ptr + cpkt->size; mp++) { memop_info_t *memop = new memop_info_t; memop->offset = dwin->decode (mp->offset); memop->id = dwin->decode (mp->id); memop->signature = dwin->decode (mp->signature); memop->datatype_id = dwin->decode (mp->datatype_id); mod->pfMemops.append (memop); inst_info_t *instop = new inst_info_t; instop->type = CPF_INSTR_TYPE_PREFETCH; instop->offset = memop->offset; instop->memop = memop; mod->infoList->incorporate (instop, offsetCmp); Dprintf (DEBUG_LOADOBJ, "pf: offset=0x%04x id=0x%08x sig=0x%08x dtid=0x%08x\n", memop->offset, memop->id, memop->signature, memop->datatype_id); } Dprintf (DEBUG_LOADOBJ, "PFINSTR list of %lld for %s\n", (long long) mod->pfMemops.size (), mod->get_name ()); break; case ARCH_BRTARGET: if (mod == NULL) break; for (target_info_t *tp = (target_info_t*) (ptr + sizeof (ARCH_aninfo)); ((char*) tp) < ptr + cpkt->size; tp++) { target_info_t *bTarget = new target_info_t; bTarget->offset = dwin->decode (tp->offset); mod->bTargets.append (bTarget); } Dprintf (DEBUG_LOADOBJ, "BRTARGET list of %lld for %s\n", (long long) mod->infoList->size (), mod->get_name ()); break; default: /* Check if the prointer is valid - should be even. */ pointer_invalid = (unsigned long long) (offset + cpktsize) & 1; break; // ignore unknown packets } if (pointer_invalid) break; offset += cpktsize; } delete msg; delete dwin; if (dbeSession->is_interactive ()) theApplication->set_progress (0, NTXT ("")); return 0; } char * LoadObject::status_str (Arch_status rv, char */*arg*/) { switch (rv) { case ARCHIVE_SUCCESS: case ARCHIVE_EXIST: return NULL; case ARCHIVE_BAD_STABS: return dbe_sprintf (GTXT ("Error: unable to read symbol table of %s"), name); case ARCHIVE_ERR_SEG: return dbe_sprintf (GTXT ("Error: unable to read load object file %s"), pathname); case ARCHIVE_ERR_OPEN: return dbe_sprintf (GTXT ("Error: unable to open file %s"), pathname); case ARCHIVE_ERR_MAP: return dbe_sprintf (GTXT ("Error: unable to map file %s"), pathname); case ARCHIVE_WARN_CHECKSUM: return dbe_sprintf (GTXT ("Note: checksum differs from that recorded in experiment for %s"), name); case ARCHIVE_WARN_MTIME: return dbe_sprintf (GTXT ("Warning: last-modified time differs from that recorded in experiment for %s"), name); case ARCHIVE_WARN_HOST: return dbe_sprintf (GTXT ("Try running er_archive -F on the experiment, on the host where it was recorded")); case ARCHIVE_ERR_VERSION: return dbe_sprintf (GTXT ("Error: Wrong version of archive for %s"), pathname); case ARCHIVE_NO_STABS: return dbe_sprintf (GTXT ("Note: no stabs or dwarf information in %s"), name); case ARCHIVE_WRONG_ARCH: #if ARCH(SPARC) return dbe_sprintf (GTXT ("Error: file %s is built for Intel, and can't be read on SPARC"), name); #else return dbe_sprintf (GTXT ("Error: file %s is built for SPARC, and can't be read on Intel"), name); #endif case ARCHIVE_NO_LIBDWARF: return dbe_strdup (GTXT ("Warning: no libdwarf found to read DWARF symbol tables")); case ARCHIVE_NO_DWARF: return dbe_sprintf (GTXT ("Note: no DWARF symbol table in %s"), name); default: return dbe_sprintf (GTXT ("Warning: unexpected archive error %d"), (int) rv); } } uint32_t LoadObject::get_checksum () { char *errmsg = NULL; uint32_t crcval = get_cksum (pathname, &errmsg); if (0 == crcval && errmsg) { warnq->append (new Emsg (CMSG_ERROR, errmsg)); free (errmsg); } return crcval; } static char* get_module_map_key (Module *mod) { return mod->lang_code == Sp_lang_java ? mod->get_name () : mod->file_name; } Module * LoadObject::get_comparable_Module (Module *mod) { if (mod->loadobject == this) return mod; if (get_module_map_key (mod) == NULL) return NULL; if (seg_modules_map == NULL) { seg_modules_map = new HashMap; for (int i = 0; i < seg_modules->size (); i++) { Module *m = seg_modules->fetch (i); char *key = get_module_map_key (m); if (key) { seg_modules_map->put (m->file_name, m); char *bname = get_basename (key); if (bname != key) seg_modules_map->put (bname, m); } } } char *key = get_module_map_key (mod); Module *cmpMod = seg_modules_map->get (key); if (cmpMod && cmpMod->comparable_objs == NULL) return cmpMod; char *bname = get_basename (key); if (bname != key) { cmpMod = seg_modules_map->get (bname); if (cmpMod && cmpMod->comparable_objs == NULL) return cmpMod; } return NULL; } Vector * LoadObject::get_comparable_objs () { update_comparable_objs (); if (comparable_objs || dbeSession->expGroups->size () <= 1) return comparable_objs; comparable_objs = new Vector(dbeSession->expGroups->size ()); for (int i = 0, sz = dbeSession->expGroups->size (); i < sz; i++) { ExpGroup *gr = dbeSession->expGroups->fetch (i); Histable *h = gr->get_comparable_loadObject (this); comparable_objs->append (h); if (h) h->comparable_objs = comparable_objs; } dump_comparable_objs (); return comparable_objs; } void LoadObject::append_module (Module *mod) { seg_modules->append (mod); if (seg_modules_map == NULL) seg_modules_map = new HashMap; char *key = get_module_map_key (mod); if (key) { seg_modules_map->put (key, mod); char *bname = get_basename (key); if (bname != key) seg_modules_map->put (bname, mod); } } // LIBRARY_VISIBILITY Function * LoadObject::get_hide_function () { if (h_function == NULL) h_function = dbeSession->create_hide_function (this); return h_function; } DbeInstr * LoadObject::get_hide_instr (DbeInstr *instr) { if (h_instr == NULL) { Function *hf = get_hide_function (); h_instr = hf->create_hide_instr (instr); } return h_instr; }