aboutsummaryrefslogtreecommitdiff
path: root/gold/gold.cc
blob: fd349ddbdce72956bc84c8ccf4eef5e86b9b126c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// ld.c -- linker main function

#include "gold.h"

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>

#include "options.h"
#include "workqueue.h"
#include "dirsearch.h"
#include "readsyms.h"

namespace gold
{

const char* program_name;

void
gold_exit(bool status)
{
  exit(status ? EXIT_SUCCESS : EXIT_FAILURE);
}

void
gold_fatal(const char* msg, bool perrno)
{
  fprintf(stderr, "%s: ", program_name);
  if (perrno)
    perror(msg);
  else
    fprintf(stderr, "%s\n", msg);
  gold_exit(false);
}

void
gold_nomem()
{
  // We are out of memory, so try hard to print a reasonable message.
  // Note that we don't try to translate this message, since the
  // translation process itself will require memory.
  write(2, program_name, strlen(program_name));
  const char* const s = ": out of memory\n";
  write(2, s, strlen(s));
  gold_exit(false);
}

void
gold_unreachable()
{
  abort();
}

} // End namespace gold.

namespace
{

using namespace gold;

// Queue up the initial set of tasks for this link job.

void
queue_initial_tasks(const General_options& options,
		    const Dirsearch& search_path,
		    const Command_line::Input_argument_list& inputs,
		    Workqueue* workqueue)
{
  if (inputs.empty())
    gold_fatal(_("no input files"), false);

  // Read the input files.  We have to add the symbols to the symbol
  // table in order.  We do this by creating a separate blocker for
  // each input file.  We associate the blocker with the following
  // input file, to give us a convenient place to delete it.
  Task_token* this_blocker = NULL;
  for (Command_line::Input_argument_list::const_iterator p = inputs.begin();
       p != inputs.end();
       ++p)
    {
      Task_token* next_blocker = new Task_token();
      next_blocker->add_blocker();
      workqueue->queue(new Read_symbols(options, search_path, *p, this_blocker,
					next_blocker));
      this_blocker = next_blocker;
    }

  // workqueue->queue(new Layout(options, inputs, this_blocker));
}

} // end anonymous namespace.

int
main(int argc, char** argv)
{
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
  setlocale (LC_MESSAGES, "");
#endif
#if defined (HAVE_SETLOCALE)
  setlocale (LC_CTYPE, "");
#endif
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  gold::program_name = argv[0];

  // Handle the command line options.
  gold::Command_line command_line;
  command_line.process(argc - 1, argv + 1);

  // The work queue.
  gold::Workqueue workqueue(command_line.options());

  // The symbol table.

  // Get the search path from the -L options.
  Dirsearch search_path;
  search_path.add(&workqueue, command_line.options().search_path());

  // Queue up the first set of tasks.
  queue_initial_tasks(command_line.options(), search_path,
		      command_line.inputs(), &workqueue);

  // Run the main task processing loop.
  workqueue.process();

  gold::gold_exit(true);
}