/* Copyright (C) 2021 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 <stdio.h>
#include <unistd.h>
#include "util.h"
#include "DbeSession.h"
#include "LoadObject.h"
#include "ArchiveExp.h"
#include "DbeFile.h"
#include "CallStack.h"
#include "gp-archive.h"
#include "Function.h"
#include "Module.h"
ArchiveExp::ArchiveExp (char *path) : Experiment ()
{
force_flag = false;
copyso_flag = false;
use_fndr_archives = true;
status = find_expdir (path);
if (status == SUCCESS)
read_log_file ();
}
ArchiveExp::~ArchiveExp () { }
void
ArchiveExp::read_data (int s_option)
{
read_archives ();
read_map_file ();
if (read_java_classes_file () == SUCCESS)
{
for (int i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
{
LoadObject *lo = loadObjs->get (i);
Dprintf (DEBUG_ARCHIVE, NTXT ("%s:%d loadObjs[%d]=%-25s %s\n"),
get_basename (__FILE__), (int) __LINE__, i,
STR (lo->get_name ()), STR (lo->get_pathname ()));
if ((lo->dbeFile->filetype & DbeFile::F_JAVACLASS) == 0)
continue;
lo->isUsed = true;
if ((s_option & ARCH_EXE_ONLY) != 0)
continue;
lo->sync_read_stabs ();
}
}
if ((s_option & (ARCH_USED_EXE_ONLY | ARCH_USED_SRC_ONLY)) != 0)
{
read_frameinfo_file ();
resolveFrameInfo = true;
Vector<DataDescriptor*> *ddscr = getDataDescriptors ();
delete ddscr; // getDataDescriptors() forces reading of experiment data
CallStack *callStack = callTree ();
if (callStack)
{
if (DEBUG_ARCHIVE)
{
Dprintf (DEBUG_ARCHIVE, NTXT ("stacks=%p\n"), callStack);
callStack->print (NULL);
}
for (int n = 0;; n++)
{
CallStackNode *node = callStack->get_node (n);
if (node == NULL)
break;
do
{
Histable *h = node->get_instr ();
Histable::Type t = h->get_type ();
if (t == Histable::INSTR)
{
DbeInstr *dbeInstr = (DbeInstr *) h;
if (!dbeInstr->isUsed)
{
Function *func = (Function *) dbeInstr->convertto (Histable::FUNCTION);
if (!func->isUsed)
{
func->isUsed = true;
func->module->isUsed = true;
func->module->loadobject->isUsed = true;
}
DbeLine *dbeLine = (DbeLine *) dbeInstr->convertto (Histable::LINE);
if (dbeLine)
dbeLine->sourceFile->isUsed = true;
}
}
else if (t == Histable::LINE)
{
DbeLine * dbeLine = (DbeLine *) h;
dbeLine->sourceFile->isUsed = true;
}
node = node->ancestor;
}
while (node);
}
}
}
}
char *
ArchiveExp::createLinkToFndrArchive (LoadObject *lo, int /* hide_msg */)
{
// For example, archives of libc.so will be:
// <exp>/archives/<libc.so_check_sum>
// <exp>/M_r0.er/archives/libc.so_<hash> -> ../../archives/<libc.so_check_sum>
if (!create_dir (get_fndr_arch_name ()))
{
fprintf (stderr, GTXT ("Unable to create directory `%s'\n"), get_fndr_arch_name ());
return NULL;
}
uint32_t checksum = lo->get_checksum ();
char *linkName = dbe_sprintf (NTXT ("../../%s/%u"), SP_ARCHIVES_DIR, checksum);
char *nm = lo->get_pathname ();
char *symLinkName = getNameInArchive (nm, false);
if (symlink (linkName, symLinkName) != 0)
{
fprintf (stderr, GTXT ("Unable to create link `%s' -> `%s'\n"),
symLinkName, linkName);
free (linkName);
free (symLinkName);
return NULL;
}
free (linkName);
free (symLinkName);
// Return a full path inside founder archive:
return dbe_sprintf (NTXT ("%s/%u"), get_fndr_arch_name (), checksum);
}