| /* Copyright (C) 2025 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 "DbeSession.h" |
| #include "Function.h" |
| #include "LoadObject.h" |
| #include "Module.h" |
| #include "Symbol.h" |
| |
| |
| template<> void Vector<Symbol *>::dump (const char *msg) |
| { |
| if (msg == NULL) |
| msg = "#"; |
| Dprintf (1, NTXT ("\n%s Vector<Symbol *> [%lld]\n"), msg, (long long) size ()); |
| if (size () > 0) |
| Dprintf (1, " value | img_offset | size | flags|local_ind|\n"); |
| for (long i = 0, sz = size (); i < sz; i++) |
| { |
| Symbol *sp = get (i); |
| Dprintf (1, " %3ld ", i); |
| sp->dump (); |
| } |
| if (size () > 0) |
| Dprintf (1, "===== END of Symbol::dump: %s =========\n\n", msg); |
| } |
| |
| void |
| Symbol::dump (const char *msg) |
| { |
| if (msg) |
| Dprintf (1, "%s\n", msg); |
| Dprintf (1, "%8lld |%11lld |%6d |%5d |%8d |%s\n", (long long) value, |
| (long long) img_offset, (int) size, flags, local_ind, |
| name ? name : "NULL"); |
| } |
| |
| Symbol::Symbol (Vector<Symbol*> *vec) |
| { |
| func = NULL; |
| lang_code = Sp_lang_unknown; |
| value = 0; |
| save = 0; |
| size = 0; |
| img_offset = 0; |
| name = NULL; |
| alias = NULL; |
| local_ind = -1; |
| flags = 0; |
| defined = false; |
| if (vec) |
| vec->append (this); |
| } |
| |
| Symbol::~Symbol () |
| { |
| free (name); |
| } |
| |
| static int |
| cmpSym (const void *a, const void *b) |
| { |
| Symbol *item1 = *((Symbol **) a); |
| Symbol *item2 = *((Symbol **) b); |
| return (item1->value > item2->value) ? 1 : |
| (item1->value == item2->value) ? 0 : -1; |
| } |
| |
| static int |
| cmpSymName (const void *a, const void *b) |
| { |
| Symbol *item1 = *((Symbol **) a); |
| Symbol *item2 = *((Symbol **) b); |
| return strcmp (item1->name, item2->name); |
| } |
| |
| Symbol * |
| Symbol::get_symbol (Vector<Symbol*> *syms, uint64_t pc) |
| { |
| if (syms != NULL && pc != 0) |
| { |
| Symbol *sp = new Symbol; |
| sp->value = pc; |
| long i = syms->bisearch (0, -1, &sp, cmpSym); |
| delete sp; |
| if (i != -1) |
| return syms->get (i)->cardinal (); |
| } |
| return NULL; |
| } |
| |
| Symbol * |
| Symbol::get_symbol (Vector<Symbol*> *syms, char *linker_name) |
| { |
| if (syms != NULL && linker_name != NULL) |
| { |
| Symbol *sp = new Symbol; |
| sp->name = linker_name; |
| long i = syms->bisearch (0, -1, &sp, cmpSymName); |
| sp->name = NULL; |
| delete sp; |
| if (i != -1) |
| return syms->get (i)->cardinal (); |
| } |
| return NULL; |
| } |
| |
| Vector<Symbol *> * |
| Symbol::sort_by_name (Vector<Symbol *> *syms) |
| { |
| if (VecSize (syms) == 0) |
| return NULL; |
| Vector<Symbol *> *symbols = syms->copy (); |
| symbols->sort (cmpSymName); |
| return symbols; |
| } |
| |
| Vector<Symbol *> * |
| Symbol::find_symbols (Vector<Symbol*> *syms, Vector<Range *> *ranges, |
| Vector<Symbol *> *symbols) |
| { |
| // 'syms' and 'ranges' must already be sorted. |
| // return symbols matched by 'ranges' |
| if (VecSize (syms) == 0 || VecSize (ranges) == 0) |
| return NULL; |
| |
| // Use binary search to find a suitable index in 'syms' |
| int ind = 0; |
| uint64_t addr = ranges->get (0)->low; |
| for (int lo = 0, hi = syms->size (); lo < hi;) |
| { |
| int mid = (hi + lo) >> 1; |
| Symbol *sym = syms->get (mid); |
| if (sym->value == addr) |
| { |
| ind = mid; |
| break; |
| } |
| else if (sym->value > addr) |
| hi = mid - 1; |
| else |
| { |
| ind = mid; |
| lo = mid + 1; |
| } |
| } |
| |
| for (int i = 0, r_sz = ranges->size (), sz = syms->size (); ind < sz; ind++) |
| { |
| Symbol *sym = syms->get (ind); |
| while (i < r_sz) |
| { |
| Range *r = ranges->get (i); |
| if (sym->value < r->low) |
| break; |
| if (sym->value <= r->high) |
| { |
| symbols->append (sym); |
| break; |
| } |
| i++; |
| } |
| if (i >= r_sz) |
| break; |
| } |
| return symbols; |
| } |
| |
| /* Create and append a new function to the 'module'. |
| * Copy attributes (size, name, etc) from Simbol, */ |
| Function * |
| Symbol::createFunction (Module *module) |
| { |
| if (func) |
| return func; |
| func = dbeSession->createFunction (); |
| func->img_fname = module->file_name; |
| func->img_offset = img_offset; |
| func->save_addr = save; |
| func->size = size; |
| func->module = module; |
| func->set_name (name); |
| module->functions->append (func); |
| module->loadobject->functions->append (func); |
| return func; |
| } |
| |
| template<> void Vector<Range *>::dump (const char *msg) |
| { |
| Dprintf (1, NTXT ("%s Vector<Range *> [%lld]\n"), |
| msg ? msg : "#", (long long) size ()); |
| for (long i = 0, sz = size (); i < sz; i++) |
| { |
| Range *p = get (i); |
| Dprintf (1, "%3ld 0x%08llx 0x%08llx (%lld - %lld)\n", i, |
| (long long) p->low, (long long) p->high, |
| (long long) p->low, (long long) p->high); |
| } |
| } |