1/* Copyright (C) 2021 Free Software Foundation, Inc.
2   Contributed by Oracle.
3
4   This file is part of GNU Binutils.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, 51 Franklin Street - Fifth Floor, Boston,
19   MA 02110-1301, USA.  */
20
21#include "config.h"
22#include <stdio.h>
23#include <unistd.h>
24
25#include "util.h"
26#include "DbeSession.h"
27#include "LoadObject.h"
28#include "ArchiveExp.h"
29#include "DbeFile.h"
30#include "CallStack.h"
31#include "gp-archive.h"
32#include "Function.h"
33#include "Module.h"
34
35ArchiveExp::ArchiveExp (char *path) : Experiment ()
36{
37  force_flag = false;
38  copyso_flag = false;
39  use_fndr_archives = true;
40  status = find_expdir (path);
41  if (status == SUCCESS)
42    read_log_file ();
43}
44
45ArchiveExp::~ArchiveExp () { }
46
47void
48ArchiveExp::read_data (int s_option)
49{
50  read_archives ();
51  read_map_file ();
52  if (read_java_classes_file () == SUCCESS)
53    {
54      for (int i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
55	{
56	  LoadObject *lo = loadObjs->get (i);
57	  Dprintf (DEBUG_ARCHIVE, NTXT ("%s:%d loadObjs[%d]=%-25s %s\n"),
58		   get_basename (__FILE__), (int) __LINE__, i,
59		   STR (lo->get_name ()), STR (lo->get_pathname ()));
60	  if ((lo->dbeFile->filetype & DbeFile::F_JAVACLASS) == 0)
61	    continue;
62	  lo->isUsed = true;
63	  if ((s_option & ARCH_EXE_ONLY) != 0)
64	    continue;
65	  lo->sync_read_stabs ();
66	}
67    }
68  if ((s_option & (ARCH_USED_EXE_ONLY | ARCH_USED_SRC_ONLY)) != 0)
69    {
70      read_frameinfo_file ();
71      resolveFrameInfo = true;
72      Vector<DataDescriptor*> *ddscr = getDataDescriptors ();
73      delete ddscr; // getDataDescriptors() forces reading of experiment data
74      CallStack *callStack = callTree ();
75      if (callStack)
76	{
77	  if (DEBUG_ARCHIVE)
78	    {
79	      Dprintf (DEBUG_ARCHIVE, NTXT ("stacks=%p\n"), callStack);
80	      callStack->print (NULL);
81	    }
82	  for (int n = 0;; n++)
83	    {
84	      CallStackNode *node = callStack->get_node (n);
85	      if (node == NULL)
86		break;
87	      do
88		{
89		  Histable *h = node->get_instr ();
90		  Histable::Type t = h->get_type ();
91		  if (t == Histable::INSTR)
92		    {
93		      DbeInstr *dbeInstr = (DbeInstr *) h;
94		      if (!dbeInstr->isUsed)
95			{
96			  Function *func = (Function *) dbeInstr->convertto (Histable::FUNCTION);
97			  if (!func->isUsed)
98			    {
99			      func->isUsed = true;
100			      func->module->isUsed = true;
101			      func->module->loadobject->isUsed = true;
102			    }
103			  DbeLine *dbeLine = (DbeLine *) dbeInstr->convertto (Histable::LINE);
104			  if (dbeLine)
105			    dbeLine->sourceFile->isUsed = true;
106			}
107		    }
108		  else if (t == Histable::LINE)
109		    {
110		      DbeLine * dbeLine = (DbeLine *) h;
111		      dbeLine->sourceFile->isUsed = true;
112		    }
113		  node = node->ancestor;
114		}
115	      while (node);
116	    }
117	}
118    }
119}
120
121char *
122ArchiveExp::createLinkToFndrArchive (LoadObject *lo, int /* hide_msg */)
123{
124  // For example, archives of libc.so will be:
125  //  <exp>/archives/<libc.so_check_sum>
126  //  <exp>/M_r0.er/archives/libc.so_<hash> -> ../../archives/<libc.so_check_sum>
127  if (!create_dir (get_fndr_arch_name ()))
128    {
129      fprintf (stderr, GTXT ("Unable to create directory `%s'\n"), get_fndr_arch_name ());
130      return NULL;
131    }
132  uint32_t checksum = lo->get_checksum ();
133  char *linkName = dbe_sprintf (NTXT ("../../%s/%u"), SP_ARCHIVES_DIR, checksum);
134  char *nm = lo->get_pathname ();
135  char *symLinkName = getNameInArchive (nm, false);
136  if (symlink (linkName, symLinkName) != 0)
137    {
138      fprintf (stderr, GTXT ("Unable to create link `%s' -> `%s'\n"),
139	       symLinkName, linkName);
140      free (linkName);
141      free (symLinkName);
142      return NULL;
143    }
144  free (linkName);
145  free (symLinkName);
146
147  // Return a full path inside founder archive:
148  return dbe_sprintf (NTXT ("%s/%u"), get_fndr_arch_name (), checksum);
149}
150