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 "util.h"
23#include "ExpGroup.h"
24#include "Experiment.h"
25#include "LoadObject.h"
26#include "DbeSession.h"
27
28//////////////////////////////////////////////////////////
29//  class ExpGroup
30
31int ExpGroup::phaseCompareIdx = 0;
32
33ExpGroup::ExpGroup (char *nm)
34{
35  name = dbe_strdup (nm);
36  canonical_path (name);
37  exps = new Vector<Experiment*>;
38  founder = NULL;
39  groupId = 0;
40  phaseCompareIdx++;
41  loadObjs = NULL;
42  loadObjsMap = NULL;
43}
44
45ExpGroup::~ExpGroup ()
46{
47  phaseCompareIdx++;
48  free (name);
49  delete exps;
50  delete loadObjs;
51  delete loadObjsMap;
52}
53
54void
55ExpGroup::append (Experiment *exp)
56{
57  for (int i = 0, sz = exps->size (); i < sz; i++)
58    {
59      Experiment *e = exps->fetch (i);
60      if (exp == e)
61	return;
62    }
63  exps->append (exp);
64  if (exps->size () == 1)
65    founder = exp;
66}
67
68void
69ExpGroup::drop_experiment (Experiment *exp)
70{
71  for (int i = 0, sz = exps->size (); i < sz; i++)
72    {
73      Experiment *e = exps->fetch (i);
74      if (exp == e)
75	{
76	  exps->remove (i);
77	  break;
78	}
79    }
80  if (founder == exp)
81    founder = NULL;
82}
83
84Vector<Experiment*> *
85ExpGroup::get_founders ()
86{
87  Vector<Experiment*> *expList = NULL;
88  for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++)
89    {
90      Experiment *exp = exps->fetch (i);
91      if (exp->founder_exp == NULL)
92	{
93	  if (expList == NULL)
94	    expList = new Vector<Experiment*>;
95	  expList->append (exp);
96	}
97    }
98  return expList;
99}
100
101void
102ExpGroup::create_list_of_loadObjects ()
103{
104  if (loadObjs == NULL)
105    {
106      loadObjs = new Vector<LoadObject*>();
107      loadObjsMap = new DefaultMap<LoadObject*, int>();
108      for (int i = 0, sz = exps ? exps->size () : 0; i < sz; i++)
109	{
110	  Experiment *exp = exps->fetch (i);
111	  for (int i1 = 0, sz1 = VecSize(exp->loadObjs); i1 < sz1; i1++)
112	    {
113	      LoadObject *lo = exp->loadObjs->fetch (i1);
114	      if (!loadObjsMap->get (lo))
115		{
116		  loadObjs->append (lo);
117		  loadObjsMap->put (lo, loadObjs->size ());
118		}
119	    }
120	}
121    }
122}
123
124LoadObject *
125ExpGroup::get_comparable_loadObject (LoadObject *lo)
126{
127  create_list_of_loadObjects ();
128  if (loadObjsMap->get (lo))
129    return lo;
130  if ((lo->flags & SEG_FLAG_EXE) != 0)
131    if (dbeSession->expGroups->size () == dbeSession->nexps ())
132      for (int i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
133	{
134	  LoadObject *lobj = loadObjs->fetch (i);
135	  if ((lobj->flags & SEG_FLAG_EXE) != 0)
136	    return lobj;
137	}
138
139  long first_ind = -1;
140  char *bname = get_basename (lo->get_pathname ());
141  for (long i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
142    {
143      LoadObject *lobj = loadObjs->get (i);
144      if (lobj->comparable_objs == NULL
145	  && strcmp (bname, get_basename (lobj->get_pathname ())) == 0)
146	{
147	  if (lo->platform == lobj->platform)
148	    {
149	      if ((lo->flags & SEG_FLAG_DYNAMIC) != 0)
150		{
151		  if (dbe_strcmp (lo->firstExp->uarglist,
152				  lobj->firstExp->uarglist) == 0)
153		    return lobj;
154		}
155	      else
156		return lobj;
157	    }
158	  if (first_ind == -1)
159	    first_ind = i;
160	}
161    }
162  return first_ind == -1 ? NULL : loadObjs->get (first_ind);
163}
164