2006-09-30 03:58:17 +08:00
|
|
|
// reloc.h -- relocate input files for gold -*- C++ -*-
|
|
|
|
|
2017-01-02 11:36:43 +08:00
|
|
|
// Copyright (C) 2006-2017 Free Software Foundation, Inc.
|
2007-09-23 05:02:10 +08:00
|
|
|
// Written by Ian Lance Taylor <iant@google.com>.
|
|
|
|
|
|
|
|
// This file is part of gold.
|
|
|
|
|
|
|
|
// 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 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
|
|
|
// MA 02110-1301, USA.
|
|
|
|
|
2006-09-30 03:58:17 +08:00
|
|
|
#ifndef GOLD_RELOC_H
|
|
|
|
#define GOLD_RELOC_H
|
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
#include <vector>
|
2009-06-24 02:10:42 +08:00
|
|
|
#ifdef HAVE_BYTESWAP_H
|
2006-10-21 04:40:49 +08:00
|
|
|
#include <byteswap.h>
|
2009-06-24 02:10:42 +08:00
|
|
|
#endif
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-11-10 07:16:54 +08:00
|
|
|
#include "elfcpp.h"
|
2006-09-30 03:58:17 +08:00
|
|
|
#include "workqueue.h"
|
|
|
|
|
|
|
|
namespace gold
|
|
|
|
{
|
|
|
|
|
2006-11-30 01:56:40 +08:00
|
|
|
class General_options;
|
2007-11-13 04:35:21 +08:00
|
|
|
class Object;
|
2006-11-07 06:46:08 +08:00
|
|
|
class Relobj;
|
2012-04-26 08:07:21 +08:00
|
|
|
struct Read_relocs_data;
|
2006-11-30 01:56:40 +08:00
|
|
|
class Symbol;
|
2006-11-04 02:26:11 +08:00
|
|
|
class Layout;
|
2008-02-06 16:13:50 +08:00
|
|
|
class Output_data;
|
2007-11-16 07:46:46 +08:00
|
|
|
class Output_section;
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2006-12-01 07:52:50 +08:00
|
|
|
template<int size>
|
|
|
|
class Sized_symbol;
|
|
|
|
|
2007-05-17 01:42:48 +08:00
|
|
|
template<int size, bool big_endian>
|
2011-05-25 05:41:10 +08:00
|
|
|
class Sized_relobj_file;
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
template<int size>
|
|
|
|
class Symbol_value;
|
|
|
|
|
2006-12-01 07:52:50 +08:00
|
|
|
template<int sh_type, bool dynamic, int size, bool big_endian>
|
|
|
|
class Output_data_reloc;
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// A class to read the relocations for an object file, and then queue
|
|
|
|
// up a task to see if they require any GOT/PLT/COPY relocations in
|
|
|
|
// the symbol table.
|
|
|
|
|
|
|
|
class Read_relocs : public Task
|
|
|
|
{
|
|
|
|
public:
|
2010-02-12 12:33:53 +08:00
|
|
|
// THIS_BLOCKER and NEXT_BLOCKER are passed along to a Scan_relocs
|
|
|
|
// or Gc_process_relocs task, so that they run in a deterministic
|
|
|
|
// order.
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
Read_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
|
2010-02-12 12:33:53 +08:00
|
|
|
Task_token* this_blocker, Task_token* next_blocker)
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
: symtab_(symtab), layout_(layout), object_(object),
|
2010-02-12 12:33:53 +08:00
|
|
|
this_blocker_(this_blocker), next_blocker_(next_blocker)
|
2006-10-21 04:40:49 +08:00
|
|
|
{ }
|
|
|
|
|
|
|
|
// The standard Task methods.
|
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
Task_token*
|
|
|
|
is_runnable();
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
void
|
|
|
|
locks(Task_locker*);
|
2006-10-21 04:40:49 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
run(Workqueue*);
|
|
|
|
|
2007-11-22 08:05:51 +08:00
|
|
|
std::string
|
|
|
|
get_name() const;
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
private:
|
|
|
|
Symbol_table* symtab_;
|
2006-11-04 02:26:11 +08:00
|
|
|
Layout* layout_;
|
2006-11-07 06:46:08 +08:00
|
|
|
Relobj* object_;
|
2010-02-12 12:33:53 +08:00
|
|
|
Task_token* this_blocker_;
|
|
|
|
Task_token* next_blocker_;
|
2006-10-21 04:40:49 +08:00
|
|
|
};
|
|
|
|
|
2009-01-28 10:25:33 +08:00
|
|
|
// Process the relocs to figure out which sections are garbage.
|
|
|
|
// Very similar to scan relocs.
|
|
|
|
|
|
|
|
class Gc_process_relocs : public Task
|
|
|
|
{
|
|
|
|
public:
|
2010-02-12 12:33:53 +08:00
|
|
|
// THIS_BLOCKER prevents this task from running until the previous
|
|
|
|
// one is finished. NEXT_BLOCKER prevents the next task from
|
|
|
|
// running.
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
Gc_process_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
|
2010-02-12 12:33:53 +08:00
|
|
|
Read_relocs_data* rd, Task_token* this_blocker,
|
|
|
|
Task_token* next_blocker)
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
: symtab_(symtab), layout_(layout), object_(object), rd_(rd),
|
2010-02-12 12:33:53 +08:00
|
|
|
this_blocker_(this_blocker), next_blocker_(next_blocker)
|
2009-01-28 10:25:33 +08:00
|
|
|
{ }
|
|
|
|
|
2010-02-12 12:33:53 +08:00
|
|
|
~Gc_process_relocs();
|
|
|
|
|
2009-01-28 10:25:33 +08:00
|
|
|
// The standard Task methods.
|
|
|
|
|
|
|
|
Task_token*
|
|
|
|
is_runnable();
|
|
|
|
|
|
|
|
void
|
|
|
|
locks(Task_locker*);
|
|
|
|
|
|
|
|
void
|
|
|
|
run(Workqueue*);
|
|
|
|
|
|
|
|
std::string
|
|
|
|
get_name() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Symbol_table* symtab_;
|
|
|
|
Layout* layout_;
|
|
|
|
Relobj* object_;
|
|
|
|
Read_relocs_data* rd_;
|
2010-02-12 12:33:53 +08:00
|
|
|
Task_token* this_blocker_;
|
|
|
|
Task_token* next_blocker_;
|
2009-01-28 10:25:33 +08:00
|
|
|
};
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Scan the relocations for an object to see if they require any
|
|
|
|
// GOT/PLT/COPY relocations.
|
|
|
|
|
|
|
|
class Scan_relocs : public Task
|
|
|
|
{
|
|
|
|
public:
|
2010-02-12 12:33:53 +08:00
|
|
|
// THIS_BLOCKER prevents this task from running until the previous
|
|
|
|
// one is finished. NEXT_BLOCKER prevents the next task from
|
|
|
|
// running.
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
Scan_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
|
2010-02-12 12:33:53 +08:00
|
|
|
Read_relocs_data* rd, Task_token* this_blocker,
|
|
|
|
Task_token* next_blocker)
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
: symtab_(symtab), layout_(layout), object_(object), rd_(rd),
|
2010-02-12 12:33:53 +08:00
|
|
|
this_blocker_(this_blocker), next_blocker_(next_blocker)
|
2006-10-21 04:40:49 +08:00
|
|
|
{ }
|
|
|
|
|
2010-02-12 12:33:53 +08:00
|
|
|
~Scan_relocs();
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// The standard Task methods.
|
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
Task_token*
|
|
|
|
is_runnable();
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
void
|
|
|
|
locks(Task_locker*);
|
2006-10-21 04:40:49 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
run(Workqueue*);
|
|
|
|
|
2007-11-22 08:05:51 +08:00
|
|
|
std::string
|
|
|
|
get_name() const;
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
private:
|
|
|
|
Symbol_table* symtab_;
|
2006-11-04 02:26:11 +08:00
|
|
|
Layout* layout_;
|
2006-11-07 06:46:08 +08:00
|
|
|
Relobj* object_;
|
2006-10-21 04:40:49 +08:00
|
|
|
Read_relocs_data* rd_;
|
2010-02-12 12:33:53 +08:00
|
|
|
Task_token* this_blocker_;
|
|
|
|
Task_token* next_blocker_;
|
2006-10-21 04:40:49 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// A class to perform all the relocations for an object file.
|
|
|
|
|
2006-09-30 03:58:17 +08:00
|
|
|
class Relocate_task : public Task
|
|
|
|
{
|
|
|
|
public:
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
Relocate_task(const Symbol_table* symtab, const Layout* layout,
|
|
|
|
Relobj* object, Output_file* of,
|
2007-11-09 15:00:15 +08:00
|
|
|
Task_token* input_sections_blocker,
|
|
|
|
Task_token* output_sections_blocker, Task_token* final_blocker)
|
* object.h (class Relobj): Drop options parameter from
gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs,
do_scan_relocs, do_relocate. Change all callers.
(class Sized_relobj): Drop options parameters from
do_gc_process_relocs, do_scan_relocs, do_relocate,
do_relocate_sections, relocate_sections, emit_relocs_scan,
emit_relocs_scan_reltype. Change all callers.
(struct Relocate_info): Remove options field and all references to
it.
* reloc.h (class Read_relocs): Remove options constructor
parameter and options_ field. Change all callers.
(class Gc_process_relocs, class Scan_relocs): Likewise.
(class Relocate_task): Likewise.
* target-reloc.h (scan_relocs): Remove options parameter. Change
all callers.
(scan_relocatable_relocs): Likewise.
* target.h (class Sized_target): Remove options parameter from
gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change
all callers.
* gc.h (gc_process_relocs): Remove options parameter. Change all
callers.
* arm.cc: Update functions to remove options parameters.
* i386.cc: Likewise.
* powerpc.cc: Likewise.
* sparc.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
2009-10-29 13:16:23 +08:00
|
|
|
: symtab_(symtab), layout_(layout), object_(object), of_(of),
|
|
|
|
input_sections_blocker_(input_sections_blocker),
|
2007-11-09 15:00:15 +08:00
|
|
|
output_sections_blocker_(output_sections_blocker),
|
|
|
|
final_blocker_(final_blocker)
|
2006-09-30 03:58:17 +08:00
|
|
|
{ }
|
|
|
|
|
|
|
|
// The standard Task methods.
|
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
Task_token*
|
|
|
|
is_runnable();
|
2006-09-30 03:58:17 +08:00
|
|
|
|
2007-12-15 03:00:21 +08:00
|
|
|
void
|
|
|
|
locks(Task_locker*);
|
2006-09-30 03:58:17 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
run(Workqueue*);
|
|
|
|
|
2007-11-22 08:05:51 +08:00
|
|
|
std::string
|
|
|
|
get_name() const;
|
|
|
|
|
2006-09-30 03:58:17 +08:00
|
|
|
private:
|
|
|
|
const Symbol_table* symtab_;
|
2006-10-21 04:40:49 +08:00
|
|
|
const Layout* layout_;
|
2006-11-07 06:46:08 +08:00
|
|
|
Relobj* object_;
|
2006-09-30 03:58:17 +08:00
|
|
|
Output_file* of_;
|
2007-11-09 15:00:15 +08:00
|
|
|
Task_token* input_sections_blocker_;
|
|
|
|
Task_token* output_sections_blocker_;
|
2006-09-30 03:58:17 +08:00
|
|
|
Task_token* final_blocker_;
|
|
|
|
};
|
|
|
|
|
2008-02-06 16:13:50 +08:00
|
|
|
// During a relocatable link, this class records how relocations
|
|
|
|
// should be handled for a single input reloc section. An instance of
|
|
|
|
// this class is created while scanning relocs, and it is used while
|
|
|
|
// processing relocs.
|
|
|
|
|
|
|
|
class Relocatable_relocs
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// We use a vector of unsigned char to indicate how the input relocs
|
|
|
|
// should be handled. Each element is one of the following values.
|
|
|
|
// We create this vector when we initially scan the relocations.
|
|
|
|
enum Reloc_strategy
|
|
|
|
{
|
|
|
|
// Copy the input reloc. Don't modify it other than updating the
|
|
|
|
// r_offset field and the r_sym part of the r_info field.
|
|
|
|
RELOC_COPY,
|
|
|
|
// Copy the input reloc which is against an STT_SECTION symbol.
|
|
|
|
// Update the r_offset and r_sym part of the r_info field. Adjust
|
|
|
|
// the addend by subtracting the value of the old local symbol and
|
|
|
|
// adding the value of the new local symbol. The addend is in the
|
|
|
|
// SHT_RELA reloc and the contents of the data section do not need
|
|
|
|
// to be changed.
|
|
|
|
RELOC_ADJUST_FOR_SECTION_RELA,
|
2008-02-28 06:38:18 +08:00
|
|
|
// Like RELOC_ADJUST_FOR_SECTION_RELA but the addend should not be
|
|
|
|
// adjusted.
|
|
|
|
RELOC_ADJUST_FOR_SECTION_0,
|
2008-02-06 16:13:50 +08:00
|
|
|
// Like RELOC_ADJUST_FOR_SECTION_RELA but the contents of the
|
|
|
|
// section need to be changed. The number indicates the number of
|
|
|
|
// bytes in the addend in the section contents.
|
|
|
|
RELOC_ADJUST_FOR_SECTION_1,
|
|
|
|
RELOC_ADJUST_FOR_SECTION_2,
|
|
|
|
RELOC_ADJUST_FOR_SECTION_4,
|
|
|
|
RELOC_ADJUST_FOR_SECTION_8,
|
2011-11-10 08:41:53 +08:00
|
|
|
// Like RELOC_ADJUST_FOR_SECTION_4 but for unaligned relocs.
|
|
|
|
RELOC_ADJUST_FOR_SECTION_4_UNALIGNED,
|
2008-02-06 16:13:50 +08:00
|
|
|
// Discard the input reloc--process it completely when relocating
|
|
|
|
// the data section contents.
|
|
|
|
RELOC_DISCARD,
|
|
|
|
// An input reloc which is not discarded, but which requires
|
|
|
|
// target specific processing in order to update it.
|
|
|
|
RELOC_SPECIAL
|
|
|
|
};
|
|
|
|
|
|
|
|
Relocatable_relocs()
|
|
|
|
: reloc_strategies_(), output_reloc_count_(0), posd_(NULL)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
// Record the number of relocs.
|
|
|
|
void
|
|
|
|
set_reloc_count(size_t reloc_count)
|
|
|
|
{ this->reloc_strategies_.reserve(reloc_count); }
|
|
|
|
|
|
|
|
// Record what to do for the next reloc.
|
|
|
|
void
|
2009-12-15 03:53:05 +08:00
|
|
|
set_next_reloc_strategy(Reloc_strategy strategy)
|
2008-02-06 16:13:50 +08:00
|
|
|
{
|
2009-12-15 03:53:05 +08:00
|
|
|
this->reloc_strategies_.push_back(static_cast<unsigned char>(strategy));
|
|
|
|
if (strategy != RELOC_DISCARD)
|
2008-02-06 16:13:50 +08:00
|
|
|
++this->output_reloc_count_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Record the Output_data associated with this reloc section.
|
|
|
|
void
|
|
|
|
set_output_data(Output_data* posd)
|
|
|
|
{
|
|
|
|
gold_assert(this->posd_ == NULL);
|
|
|
|
this->posd_ = posd;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the Output_data associated with this reloc section.
|
|
|
|
Output_data*
|
|
|
|
output_data() const
|
|
|
|
{ return this->posd_; }
|
|
|
|
|
|
|
|
// Return what to do for reloc I.
|
|
|
|
Reloc_strategy
|
|
|
|
strategy(unsigned int i) const
|
|
|
|
{
|
|
|
|
gold_assert(i < this->reloc_strategies_.size());
|
|
|
|
return static_cast<Reloc_strategy>(this->reloc_strategies_[i]);
|
|
|
|
}
|
|
|
|
|
[GOLD] Relocate::relocate() params
Some linker code editing needs to change multiple insns. In some
cases multiple relocations are involved and it is not sufficient to
make the changes independently as relocations are processed, because
doing so might lead to a partial edit. So in order to safely edit we
need all the relocations available in relocate(). Also, to emit
edited relocs corresponding to the edited code sequence we need some
way to pass information from relocate() to relocate_relocs(),
particularly if the edit depends on insns. We can't modify input
relocs in relocate() as they are mmapped PROT_READ, nor it is
particularly clean to write relocs to the output at that stage. So
add a Relocatable_relocs* field to relinfo to mark edited relocs.
Given that relocate is passed the raw reloc pointer, it makes sense to
remove the rel/rela parameter and r_type too. However, that means the
mips relocate() needs to know whether SHT_REL or SHT_RELA relocs are
being processed. So add a rel_type for mips, which also has the
benefit of removing relocate() overloading there.
This patch adds the infrastructure without making use of it.
Note that relinfo->rr will be NULL if not outputting relocations.
* object.h (struct Relocate_info): Add "rr".
* reloc.h (Relocatable_relocs::set_strategy): New accessor.
* reloc.cc (Sized_relobj_file::do_relocate_sections): Init
relinfo.rr for relocate_section and relocate_relocs.
* powerpc.cc (relocate): Add rel_type and preloc parameters.
Delete rela and r_type params, instead recalculate these from
preloc.
(relocate_relocs): Delete Relocatable_relocs* param, instead
use relinfo->rr.
* aarch64.cc: Likewise.
* arm.cc: Likewise.
* i386.cc: Likewise.
* mips.cc: Likewise.
* s390.cc: Likewise.
* sparc.cc: Likewise.
* target.h: Likewise.
* tilegx.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
* target-reloc.h (relocate_section): Adjust to suit.
(apply_relocation, relocate_relocs): Likewise.
2015-12-09 07:48:30 +08:00
|
|
|
// Set the strategy for reloc I.
|
|
|
|
void
|
|
|
|
set_strategy(unsigned int i, Reloc_strategy strategy)
|
|
|
|
{
|
|
|
|
gold_assert(i < this->reloc_strategies_.size());
|
|
|
|
this->reloc_strategies_[i] = strategy;
|
|
|
|
}
|
|
|
|
|
2008-02-06 16:13:50 +08:00
|
|
|
// Return the number of relocations to create in the output file.
|
|
|
|
size_t
|
|
|
|
output_reloc_count() const
|
|
|
|
{ return this->output_reloc_count_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef std::vector<unsigned char> Reloc_strategies;
|
|
|
|
|
|
|
|
// The strategies for the input reloc. There is one entry in this
|
|
|
|
// vector for each relocation in the input section.
|
|
|
|
Reloc_strategies reloc_strategies_;
|
|
|
|
// The number of relocations to be created in the output file.
|
|
|
|
size_t output_reloc_count_;
|
|
|
|
// The output data structure associated with this relocation.
|
|
|
|
Output_data* posd_;
|
|
|
|
};
|
|
|
|
|
2016-02-06 00:27:13 +08:00
|
|
|
template<int valsize>
|
|
|
|
class Bits;
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Standard relocation routines which are used on many targets. Here
|
|
|
|
// SIZE and BIG_ENDIAN refer to the target, not the relocation type.
|
|
|
|
|
|
|
|
template<int size, bool big_endian>
|
|
|
|
class Relocate_functions
|
|
|
|
{
|
2016-02-06 00:27:13 +08:00
|
|
|
public:
|
|
|
|
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
|
|
|
typedef typename elfcpp::Elf_types<size>::Elf_Swxword Addendtype;
|
|
|
|
|
|
|
|
enum Overflow_check
|
|
|
|
{
|
2016-02-07 06:47:05 +08:00
|
|
|
// No overflow checking.
|
2016-02-06 00:27:13 +08:00
|
|
|
CHECK_NONE,
|
2016-02-07 06:47:05 +08:00
|
|
|
// Check for overflow of a signed value.
|
2016-02-06 00:27:13 +08:00
|
|
|
CHECK_SIGNED,
|
2016-02-07 06:47:05 +08:00
|
|
|
// Check for overflow of an unsigned value.
|
2016-02-06 00:27:13 +08:00
|
|
|
CHECK_UNSIGNED,
|
2016-02-07 06:47:05 +08:00
|
|
|
// Check for overflow of a signed or unsigned value.
|
|
|
|
// (i.e., no error if either signed or unsigned fits.)
|
2016-02-06 00:27:13 +08:00
|
|
|
CHECK_SIGNED_OR_UNSIGNED
|
|
|
|
};
|
|
|
|
|
|
|
|
enum Reloc_status
|
|
|
|
{
|
|
|
|
RELOC_OK,
|
|
|
|
RELOC_OVERFLOW
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Check for overflow.
|
|
|
|
template<int valsize>
|
|
|
|
static inline Reloc_status
|
|
|
|
check_overflow(Address value, Overflow_check check)
|
|
|
|
{
|
|
|
|
switch (check)
|
|
|
|
{
|
|
|
|
case CHECK_SIGNED:
|
|
|
|
if (size == 32)
|
|
|
|
return (Bits<valsize>::has_overflow32(value)
|
|
|
|
? RELOC_OVERFLOW
|
|
|
|
: RELOC_OK);
|
|
|
|
else
|
|
|
|
return (Bits<valsize>::has_overflow(value)
|
|
|
|
? RELOC_OVERFLOW
|
|
|
|
: RELOC_OK);
|
|
|
|
case CHECK_UNSIGNED:
|
|
|
|
if (size == 32)
|
|
|
|
return (Bits<valsize>::has_unsigned_overflow32(value)
|
|
|
|
? RELOC_OVERFLOW
|
|
|
|
: RELOC_OK);
|
|
|
|
else
|
|
|
|
return (Bits<valsize>::has_unsigned_overflow(value)
|
|
|
|
? RELOC_OVERFLOW
|
|
|
|
: RELOC_OK);
|
|
|
|
case CHECK_SIGNED_OR_UNSIGNED:
|
|
|
|
if (size == 32)
|
|
|
|
return (Bits<valsize>::has_signed_unsigned_overflow32(value)
|
|
|
|
? RELOC_OVERFLOW
|
|
|
|
: RELOC_OK);
|
|
|
|
else
|
|
|
|
return (Bits<valsize>::has_signed_unsigned_overflow64(value)
|
|
|
|
? RELOC_OVERFLOW
|
|
|
|
: RELOC_OK);
|
|
|
|
case CHECK_NONE:
|
|
|
|
default:
|
|
|
|
return RELOC_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple relocation with the addend in the section contents.
|
|
|
|
// VALSIZE is the size of the value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
rel(unsigned char* view, Address value, Overflow_check check)
|
2006-10-21 04:40:49 +08:00
|
|
|
{
|
2006-11-07 06:46:08 +08:00
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
2006-10-21 04:40:49 +08:00
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap<valsize, big_endian>::readval(wv);
|
|
|
|
value += addend;
|
|
|
|
elfcpp::Swap<valsize, big_endian>::
|
|
|
|
writeval(wv, static_cast<Valtype>(value));
|
|
|
|
return check_overflow<valsize>(value, check);
|
2006-10-21 04:40:49 +08:00
|
|
|
}
|
|
|
|
|
2011-11-11 04:53:36 +08:00
|
|
|
// Like the above but for relocs at unaligned addresses.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
rel_unaligned(unsigned char* view, Address value, Overflow_check check)
|
2011-11-11 04:53:36 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap_unaligned<valsize, big_endian>::Valtype
|
|
|
|
Valtype;
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap_unaligned<valsize, big_endian>::readval(view);
|
|
|
|
value += addend;
|
|
|
|
elfcpp::Swap_unaligned<valsize, big_endian>::
|
|
|
|
writeval(view, static_cast<Valtype>(value));
|
|
|
|
return check_overflow<valsize>(value, check);
|
2011-11-11 04:53:36 +08:00
|
|
|
}
|
|
|
|
|
2007-05-17 01:42:48 +08:00
|
|
|
// Do a simple relocation using a Symbol_value with the addend in
|
|
|
|
// the section contents. VALSIZE is the size of the value to
|
|
|
|
// relocate.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
2007-05-17 01:42:48 +08:00
|
|
|
rel(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2016-02-06 00:27:13 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Overflow_check check)
|
2007-05-17 01:42:48 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap<valsize, big_endian>::readval(wv);
|
|
|
|
Address value = psymval->value(object, addend);
|
|
|
|
elfcpp::Swap<valsize, big_endian>::
|
|
|
|
writeval(wv, static_cast<Valtype>(value));
|
|
|
|
return check_overflow<valsize>(value, check);
|
2007-05-17 01:42:48 +08:00
|
|
|
}
|
|
|
|
|
2011-11-10 08:41:53 +08:00
|
|
|
// Like the above but for relocs at unaligned addresses.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
2011-11-10 08:41:53 +08:00
|
|
|
rel_unaligned(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2016-02-06 00:27:13 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Overflow_check check)
|
2011-11-10 08:41:53 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap_unaligned<valsize, big_endian>::Valtype
|
|
|
|
Valtype;
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap_unaligned<valsize, big_endian>::readval(view);
|
|
|
|
Address value = psymval->value(object, addend);
|
|
|
|
elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2011-11-10 08:41:53 +08:00
|
|
|
}
|
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do a simple relocation with the addend in the relocation.
|
|
|
|
// VALSIZE is the size of the value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
rela(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Overflow_check check)
|
2007-10-01 08:05:08 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
value += addend;
|
|
|
|
elfcpp::Swap<valsize, big_endian>::writeval(wv, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2007-10-01 08:05:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do a simple relocation using a symbol value with the addend in
|
|
|
|
// the relocation. VALSIZE is the size of the value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
2007-10-01 08:05:08 +08:00
|
|
|
rela(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend,
|
|
|
|
Overflow_check check)
|
2007-10-01 08:05:08 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
Address value = psymval->value(object, addend);
|
|
|
|
elfcpp::Swap<valsize, big_endian>::writeval(wv, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2007-10-01 08:05:08 +08:00
|
|
|
}
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple PC relative relocation with the addend in the section
|
|
|
|
// contents. VALSIZE is the size of the value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
pcrel(unsigned char* view, Address value, Address address,
|
|
|
|
Overflow_check check)
|
2006-10-21 04:40:49 +08:00
|
|
|
{
|
2006-11-07 06:46:08 +08:00
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
2006-10-21 04:40:49 +08:00
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap<valsize, big_endian>::readval(wv);
|
|
|
|
value = value + addend - address;
|
|
|
|
elfcpp::Swap<valsize, big_endian>::writeval(wv, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2006-10-21 04:40:49 +08:00
|
|
|
}
|
|
|
|
|
2011-11-11 04:53:36 +08:00
|
|
|
// Like the above but for relocs at unaligned addresses.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
pcrel_unaligned(unsigned char* view, Address value, Address address,
|
|
|
|
Overflow_check check)
|
2011-11-11 04:53:36 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap_unaligned<valsize, big_endian>::readval(view);
|
|
|
|
value = value + addend - address;
|
|
|
|
elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2011-11-11 04:53:36 +08:00
|
|
|
}
|
|
|
|
|
2007-05-17 01:42:48 +08:00
|
|
|
// Do a simple PC relative relocation with a Symbol_value with the
|
|
|
|
// addend in the section contents. VALSIZE is the size of the
|
|
|
|
// value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
2007-05-17 01:42:48 +08:00
|
|
|
pcrel(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
2007-05-17 01:42:48 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
Valtype addend = elfcpp::Swap<valsize, big_endian>::readval(wv);
|
|
|
|
Address value = psymval->value(object, addend) - address;
|
|
|
|
elfcpp::Swap<valsize, big_endian>::writeval(wv, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2007-05-17 01:42:48 +08:00
|
|
|
}
|
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do a simple PC relative relocation with the addend in the
|
|
|
|
// relocation. VALSIZE is the size of the value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
pcrela(unsigned char* view, Address value, Addendtype addend, Address address,
|
|
|
|
Overflow_check check)
|
2007-10-01 08:05:08 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
value = value + addend - address;
|
|
|
|
elfcpp::Swap<valsize, big_endian>::writeval(wv, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2007-10-01 08:05:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do a simple PC relative relocation with a Symbol_value with the
|
|
|
|
// addend in the relocation. VALSIZE is the size of the value.
|
|
|
|
template<int valsize>
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
2007-10-01 08:05:08 +08:00
|
|
|
pcrela(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
2007-10-01 08:05:08 +08:00
|
|
|
{
|
|
|
|
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
|
|
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
2016-02-06 00:27:13 +08:00
|
|
|
Address value = psymval->value(object, addend) - address;
|
|
|
|
elfcpp::Swap<valsize, big_endian>::writeval(wv, value);
|
|
|
|
return check_overflow<valsize>(value, check);
|
2007-10-01 08:05:08 +08:00
|
|
|
}
|
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
typedef Relocate_functions<size, big_endian> This;
|
|
|
|
|
2016-02-06 00:27:13 +08:00
|
|
|
public:
|
2007-05-17 01:42:48 +08:00
|
|
|
// Do a simple 8-bit REL relocation with the addend in the section
|
|
|
|
// contents.
|
2006-10-21 04:40:49 +08:00
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rel8(unsigned char* view, Address value)
|
|
|
|
{ This::template rel<8>(view, value, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel8_check(unsigned char* view, Address value, Overflow_check check)
|
|
|
|
{ return This::template rel<8>(view, value, check); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
rel8(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval)
|
2016-02-06 00:27:13 +08:00
|
|
|
{ This::template rel<8>(view, object, psymval, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel8_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rel<8>(view, object, psymval, check); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do an 8-bit RELA relocation with the addend in the relocation.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rela8(unsigned char* view, Address value, Addendtype addend)
|
|
|
|
{ This::template rela<8>(view, value, addend, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rela8_check(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rela<8>(view, value, addend, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
2007-10-02 05:25:23 +08:00
|
|
|
rela8(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend)
|
|
|
|
{ This::template rela<8>(view, object, psymval, addend, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rela8_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Addendtype addend,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rela<8>(view, object, psymval, addend, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple 8-bit PC relative relocation with the addend in the
|
2007-05-17 01:42:48 +08:00
|
|
|
// section contents.
|
2006-10-21 04:40:49 +08:00
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrel8(unsigned char* view, unsigned char value, Address address)
|
|
|
|
{ This::template pcrel<8>(view, value, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel8_check(unsigned char* view, unsigned char value, Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel<8>(view, value, address, check); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrel8(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Address address)
|
|
|
|
{ This::template pcrel<8>(view, object, psymval, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel8_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel<8>(view, object, psymval, address, check); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do a simple 8-bit PC relative RELA relocation with the addend in
|
|
|
|
// the reloc.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrela8(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<8>(view, value, addend, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrela8_check(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address, Overflow_check check)
|
|
|
|
{ return This::template pcrela<8>(view, value, addend, address, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrela8(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<8>(view, object, psymval, addend, address,
|
|
|
|
CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrela8_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Addendtype addend,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrela<8>(view, object, psymval, addend, address,
|
|
|
|
check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
2007-05-17 01:42:48 +08:00
|
|
|
// Do a simple 16-bit REL relocation with the addend in the section
|
|
|
|
// contents.
|
2006-10-21 04:40:49 +08:00
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rel16(unsigned char* view, Address value)
|
|
|
|
{ This::template rel<16>(view, value, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel16_check(unsigned char* view, Address value, Overflow_check check)
|
|
|
|
{ return This::template rel<16>(view, value, check); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
rel16(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval)
|
2016-02-06 00:27:13 +08:00
|
|
|
{ This::template rel<16>(view, object, psymval, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel16_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rel<16>(view, object, psymval, check); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do an 16-bit RELA relocation with the addend in the relocation.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rela16(unsigned char* view, Address value, Addendtype addend)
|
|
|
|
{ This::template rela<16>(view, value, addend, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rela16_check(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rela<16>(view, value, addend, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
rela16(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend)
|
|
|
|
{ This::template rela<16>(view, object, psymval, addend, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rela16_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Addendtype addend,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rela<16>(view, object, psymval, addend, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
// Do a simple 16-bit PC relative REL relocation with the addend in
|
2007-05-17 01:42:48 +08:00
|
|
|
// the section contents.
|
2006-10-21 04:40:49 +08:00
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrel16(unsigned char* view, Address value, Address address)
|
|
|
|
{ This::template pcrel<16>(view, value, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel16_check(unsigned char* view, Address value, Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel<16>(view, value, address, check); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrel16(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Address address)
|
|
|
|
{ This::template pcrel<16>(view, object, psymval, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel16_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel<16>(view, object, psymval, address, check); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do a simple 16-bit PC relative RELA relocation with the addend in
|
|
|
|
// the reloc.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrela16(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<16>(view, value, addend, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrela16_check(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address, Overflow_check check)
|
|
|
|
{ return This::template pcrela<16>(view, value, addend, address, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrela16(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<16>(view, object, psymval, addend, address,
|
|
|
|
CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrela16_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Addendtype addend,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrela<16>(view, object, psymval, addend, address,
|
|
|
|
check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple 32-bit REL relocation with the addend in the section
|
|
|
|
// contents.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rel32(unsigned char* view, Address value)
|
|
|
|
{ This::template rel<32>(view, value, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel32_check(unsigned char* view, Address value, Overflow_check check)
|
|
|
|
{ return This::template rel<32>(view, value, check); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
2011-11-11 04:53:36 +08:00
|
|
|
// Like above but for relocs at unaligned addresses.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rel32_unaligned(unsigned char* view, Address value)
|
|
|
|
{ This::template rel_unaligned<32>(view, value, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel32_unaligned_check(unsigned char* view, Address value,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rel_unaligned<32>(view, value, check); }
|
2011-11-11 04:53:36 +08:00
|
|
|
|
2007-05-17 01:42:48 +08:00
|
|
|
static inline void
|
|
|
|
rel32(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval)
|
2016-02-06 00:27:13 +08:00
|
|
|
{ This::template rel<32>(view, object, psymval, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rel32_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rel<32>(view, object, psymval, check); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2011-11-10 08:41:53 +08:00
|
|
|
// Like above but for relocs at unaligned addresses.
|
|
|
|
static inline void
|
|
|
|
rel32_unaligned(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval)
|
2016-02-06 00:27:13 +08:00
|
|
|
{ This::template rel_unaligned<32>(view, object, psymval, CHECK_NONE); }
|
2011-11-10 08:41:53 +08:00
|
|
|
|
2016-02-06 00:27:13 +08:00
|
|
|
static inline Reloc_status
|
|
|
|
rel32_unaligned_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rel_unaligned<32>(view, object, psymval, check); }
|
|
|
|
|
|
|
|
// Do a 32-bit RELA relocation with the addend in the relocation.
|
2007-10-01 08:05:08 +08:00
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rela32(unsigned char* view, Address value, Addendtype addend)
|
|
|
|
{ This::template rela<32>(view, value, addend, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rela32(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rela<32>(view, value, addend, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
rela32(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend)
|
|
|
|
{ This::template rela<32>(view, object, psymval, addend, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
rela32_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Addendtype addend,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template rela<32>(view, object, psymval, addend, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple 32-bit PC relative REL relocation with the addend in
|
|
|
|
// the section contents.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrel32(unsigned char* view, Address value, Address address)
|
|
|
|
{ This::template pcrel<32>(view, value, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel32_check(unsigned char* view, Address value, Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel<32>(view, value, address, check); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
2011-11-11 04:53:36 +08:00
|
|
|
// Unaligned version of the above.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrel32_unaligned(unsigned char* view, Address value, Address address)
|
|
|
|
{ This::template pcrel_unaligned<32>(view, value, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel32_unaligned_check(unsigned char* view, Address value, Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel_unaligned<32>(view, value, address, check); }
|
2011-11-11 04:53:36 +08:00
|
|
|
|
2007-05-17 01:42:48 +08:00
|
|
|
static inline void
|
|
|
|
pcrel32(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Address address)
|
|
|
|
{ This::template pcrel<32>(view, object, psymval, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrel32_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrel<32>(view, object, psymval, address, check); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do a simple 32-bit PC relative RELA relocation with the addend in
|
|
|
|
// the relocation.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrela32(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<32>(view, value, addend, address, CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrela32_check(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address, Overflow_check check)
|
|
|
|
{ return This::template pcrela<32>(view, value, addend, address, check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrela32(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<32>(view, object, psymval, addend, address,
|
|
|
|
CHECK_NONE); }
|
|
|
|
|
|
|
|
static inline Reloc_status
|
|
|
|
pcrela32_check(unsigned char* view,
|
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
|
|
|
const Symbol_value<size>* psymval,
|
|
|
|
Addendtype addend,
|
|
|
|
Address address,
|
|
|
|
Overflow_check check)
|
|
|
|
{ return This::template pcrela<32>(view, object, psymval, addend, address,
|
|
|
|
check); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple 64-bit REL relocation with the addend in the section
|
|
|
|
// contents.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rel64(unsigned char* view, Address value)
|
|
|
|
{ This::template rel<64>(view, value, CHECK_NONE); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
rel64(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval)
|
2016-02-06 00:27:13 +08:00
|
|
|
{ This::template rel<64>(view, object, psymval, CHECK_NONE); }
|
2006-10-21 04:40:49 +08:00
|
|
|
|
2007-10-01 08:05:08 +08:00
|
|
|
// Do a 64-bit RELA relocation with the addend in the relocation.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
rela64(unsigned char* view, Address value, Addendtype addend)
|
|
|
|
{ This::template rela<64>(view, value, addend, CHECK_NONE); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
rela64(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend)
|
|
|
|
{ This::template rela<64>(view, object, psymval, addend, CHECK_NONE); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
2006-10-21 04:40:49 +08:00
|
|
|
// Do a simple 64-bit PC relative REL relocation with the addend in
|
|
|
|
// the section contents.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrel64(unsigned char* view, Address value, Address address)
|
|
|
|
{ This::template pcrel<64>(view, value, address, CHECK_NONE); }
|
2007-05-17 01:42:48 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrel64(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-05-17 01:42:48 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Address address)
|
|
|
|
{ This::template pcrel<64>(view, object, psymval, address, CHECK_NONE); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
// Do a simple 64-bit PC relative RELA relocation with the addend in
|
|
|
|
// the relocation.
|
|
|
|
static inline void
|
2016-02-06 00:27:13 +08:00
|
|
|
pcrela64(unsigned char* view, Address value, Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<64>(view, value, addend, address, CHECK_NONE); }
|
2007-10-01 08:05:08 +08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
pcrela64(unsigned char* view,
|
2011-05-25 05:41:10 +08:00
|
|
|
const Sized_relobj_file<size, big_endian>* object,
|
2007-10-01 08:05:08 +08:00
|
|
|
const Symbol_value<size>* psymval,
|
2016-02-06 00:27:13 +08:00
|
|
|
Addendtype addend,
|
|
|
|
Address address)
|
|
|
|
{ This::template pcrela<64>(view, object, psymval, addend, address,
|
|
|
|
CHECK_NONE); }
|
2006-12-01 07:52:50 +08:00
|
|
|
};
|
|
|
|
|
2016-02-07 10:18:51 +08:00
|
|
|
// Convenience class for min and max values of a given BITS length.
|
|
|
|
|
|
|
|
template<int bits>
|
|
|
|
class Limits
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const uint64_t MAX_UNSIGNED = (1ULL << bits) - 1;
|
|
|
|
static const int64_t MAX_SIGNED = MAX_UNSIGNED >> 1;
|
|
|
|
static const int64_t MIN_SIGNED = -MAX_SIGNED - 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
class Limits<64>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const uint64_t MAX_UNSIGNED = ~0ULL;
|
|
|
|
static const int64_t MAX_SIGNED = MAX_UNSIGNED >> 1;
|
|
|
|
static const int64_t MIN_SIGNED = -MAX_SIGNED - 1;
|
|
|
|
};
|
|
|
|
|
2012-01-28 09:47:01 +08:00
|
|
|
// Integer manipulation functions used by various targets when
|
|
|
|
// performing relocations.
|
|
|
|
|
|
|
|
template<int bits>
|
|
|
|
class Bits
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Sign extend an n-bit unsigned integer stored in a uint32_t into
|
2012-02-04 04:01:01 +08:00
|
|
|
// an int32_t. BITS must be between 1 and 32.
|
2012-01-28 09:47:01 +08:00
|
|
|
static inline int32_t
|
|
|
|
sign_extend32(uint32_t val)
|
|
|
|
{
|
2012-02-04 04:01:01 +08:00
|
|
|
gold_assert(bits > 0 && bits <= 32);
|
2012-01-28 09:47:01 +08:00
|
|
|
if (bits == 32)
|
|
|
|
return static_cast<int32_t>(val);
|
|
|
|
uint32_t mask = (~static_cast<uint32_t>(0)) >> (32 - bits);
|
|
|
|
val &= mask;
|
|
|
|
uint32_t top_bit = 1U << (bits - 1);
|
|
|
|
int32_t as_signed = static_cast<int32_t>(val);
|
|
|
|
if ((val & top_bit) != 0)
|
|
|
|
as_signed -= static_cast<int32_t>(top_bit * 2);
|
|
|
|
return as_signed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return true if VAL (stored in a uint32_t) has overflowed a signed
|
|
|
|
// value with BITS bits.
|
|
|
|
static inline bool
|
|
|
|
has_overflow32(uint32_t val)
|
|
|
|
{
|
2012-02-04 04:01:01 +08:00
|
|
|
gold_assert(bits > 0 && bits <= 32);
|
2012-01-28 09:47:01 +08:00
|
|
|
if (bits == 32)
|
|
|
|
return false;
|
2016-02-07 10:18:51 +08:00
|
|
|
const int32_t max = static_cast<int32_t>(Limits<bits>::MAX_SIGNED);
|
|
|
|
const int32_t min = static_cast<int32_t>(Limits<bits>::MIN_SIGNED);
|
2012-01-28 09:47:01 +08:00
|
|
|
int32_t as_signed = static_cast<int32_t>(val);
|
|
|
|
return as_signed > max || as_signed < min;
|
|
|
|
}
|
|
|
|
|
2016-02-06 00:27:13 +08:00
|
|
|
// Return true if VAL (stored in a uint32_t) has overflowed an unsigned
|
|
|
|
// value with BITS bits.
|
|
|
|
static inline bool
|
|
|
|
has_unsigned_overflow32(uint32_t val)
|
|
|
|
{
|
|
|
|
gold_assert(bits > 0 && bits <= 32);
|
|
|
|
if (bits == 32)
|
|
|
|
return false;
|
2016-02-07 10:18:51 +08:00
|
|
|
const uint32_t max = static_cast<uint32_t>(Limits<bits>::MAX_UNSIGNED);
|
2016-02-06 00:27:13 +08:00
|
|
|
return val > max;
|
|
|
|
}
|
|
|
|
|
2012-01-28 09:47:01 +08:00
|
|
|
// Return true if VAL (stored in a uint32_t) has overflowed both a
|
|
|
|
// signed and an unsigned value. E.g.,
|
|
|
|
// Bits<8>::has_signed_unsigned_overflow32 would check -128 <= VAL <
|
|
|
|
// 255.
|
|
|
|
static inline bool
|
|
|
|
has_signed_unsigned_overflow32(uint32_t val)
|
|
|
|
{
|
2012-02-04 04:01:01 +08:00
|
|
|
gold_assert(bits > 0 && bits <= 32);
|
2012-01-28 09:47:01 +08:00
|
|
|
if (bits == 32)
|
|
|
|
return false;
|
2016-02-07 10:18:51 +08:00
|
|
|
const int32_t max = static_cast<int32_t>(Limits<bits>::MAX_UNSIGNED);
|
|
|
|
const int32_t min = static_cast<int32_t>(Limits<bits>::MIN_SIGNED);
|
2012-01-28 09:47:01 +08:00
|
|
|
int32_t as_signed = static_cast<int32_t>(val);
|
|
|
|
return as_signed > max || as_signed < min;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select bits from A and B using bits in MASK. For each n in
|
|
|
|
// [0..31], the n-th bit in the result is chosen from the n-th bits
|
|
|
|
// of A and B. A zero selects A and a one selects B.
|
|
|
|
static inline uint32_t
|
|
|
|
bit_select32(uint32_t a, uint32_t b, uint32_t mask)
|
|
|
|
{ return (a & ~mask) | (b & mask); }
|
|
|
|
|
|
|
|
// Sign extend an n-bit unsigned integer stored in a uint64_t into
|
2012-02-04 04:01:01 +08:00
|
|
|
// an int64_t. BITS must be between 1 and 64.
|
2012-01-28 09:47:01 +08:00
|
|
|
static inline int64_t
|
|
|
|
sign_extend(uint64_t val)
|
|
|
|
{
|
2012-02-04 04:01:01 +08:00
|
|
|
gold_assert(bits > 0 && bits <= 64);
|
2012-01-28 09:47:01 +08:00
|
|
|
if (bits == 64)
|
|
|
|
return static_cast<int64_t>(val);
|
|
|
|
uint64_t mask = (~static_cast<uint64_t>(0)) >> (64 - bits);
|
|
|
|
val &= mask;
|
|
|
|
uint64_t top_bit = static_cast<uint64_t>(1) << (bits - 1);
|
|
|
|
int64_t as_signed = static_cast<int64_t>(val);
|
|
|
|
if ((val & top_bit) != 0)
|
|
|
|
as_signed -= static_cast<int64_t>(top_bit * 2);
|
|
|
|
return as_signed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return true if VAL (stored in a uint64_t) has overflowed a signed
|
|
|
|
// value with BITS bits.
|
|
|
|
static inline bool
|
|
|
|
has_overflow(uint64_t val)
|
|
|
|
{
|
2012-02-04 04:01:01 +08:00
|
|
|
gold_assert(bits > 0 && bits <= 64);
|
2012-01-28 09:47:01 +08:00
|
|
|
if (bits == 64)
|
|
|
|
return false;
|
2016-02-07 10:18:51 +08:00
|
|
|
const int64_t max = Limits<bits>::MAX_SIGNED;
|
|
|
|
const int64_t min = Limits<bits>::MIN_SIGNED;
|
2012-01-28 09:47:01 +08:00
|
|
|
int64_t as_signed = static_cast<int64_t>(val);
|
|
|
|
return as_signed > max || as_signed < min;
|
|
|
|
}
|
|
|
|
|
2016-02-06 00:27:13 +08:00
|
|
|
// Return true if VAL (stored in a uint64_t) has overflowed an unsigned
|
|
|
|
// value with BITS bits.
|
|
|
|
static inline bool
|
|
|
|
has_unsigned_overflow(uint64_t val)
|
|
|
|
{
|
|
|
|
gold_assert(bits > 0 && bits <= 64);
|
|
|
|
if (bits == 64)
|
|
|
|
return false;
|
2016-02-07 10:18:51 +08:00
|
|
|
const uint64_t max = Limits<bits>::MAX_UNSIGNED;
|
2016-02-06 00:27:13 +08:00
|
|
|
return val > max;
|
|
|
|
}
|
|
|
|
|
2012-01-28 09:47:01 +08:00
|
|
|
// Return true if VAL (stored in a uint64_t) has overflowed both a
|
|
|
|
// signed and an unsigned value. E.g.,
|
|
|
|
// Bits<8>::has_signed_unsigned_overflow would check -128 <= VAL <
|
|
|
|
// 255.
|
|
|
|
static inline bool
|
|
|
|
has_signed_unsigned_overflow64(uint64_t val)
|
|
|
|
{
|
2012-02-04 04:01:01 +08:00
|
|
|
gold_assert(bits > 0 && bits <= 64);
|
2012-01-28 09:47:01 +08:00
|
|
|
if (bits == 64)
|
|
|
|
return false;
|
2016-02-07 10:18:51 +08:00
|
|
|
const int64_t max = static_cast<int64_t>(Limits<bits>::MAX_UNSIGNED);
|
|
|
|
const int64_t min = Limits<bits>::MIN_SIGNED;
|
2012-01-28 09:47:01 +08:00
|
|
|
int64_t as_signed = static_cast<int64_t>(val);
|
|
|
|
return as_signed > max || as_signed < min;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select bits from A and B using bits in MASK. For each n in
|
|
|
|
// [0..31], the n-th bit in the result is chosen from the n-th bits
|
|
|
|
// of A and B. A zero selects A and a one selects B.
|
|
|
|
static inline uint64_t
|
|
|
|
bit_select64(uint64_t a, uint64_t b, uint64_t mask)
|
|
|
|
{ return (a & ~mask) | (b & mask); }
|
|
|
|
};
|
|
|
|
|
2007-11-09 15:00:15 +08:00
|
|
|
// Track relocations while reading a section. This lets you ask for
|
|
|
|
// the relocation at a certain offset, and see how relocs occur
|
|
|
|
// between points of interest.
|
|
|
|
|
|
|
|
template<int size, bool big_endian>
|
|
|
|
class Track_relocs
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Track_relocs()
|
2007-11-13 04:35:21 +08:00
|
|
|
: prelocs_(NULL), len_(0), pos_(0), reloc_size_(0)
|
2007-11-09 15:00:15 +08:00
|
|
|
{ }
|
|
|
|
|
|
|
|
// Initialize the Track_relocs object. OBJECT is the object holding
|
|
|
|
// the reloc section, RELOC_SHNDX is the section index of the reloc
|
|
|
|
// section, and RELOC_TYPE is the type of the reloc section
|
|
|
|
// (elfcpp::SHT_REL or elfcpp::SHT_RELA). This returns false if
|
|
|
|
// something went wrong.
|
|
|
|
bool
|
2007-11-13 04:35:21 +08:00
|
|
|
initialize(Object* object, unsigned int reloc_shndx,
|
2007-11-09 15:00:15 +08:00
|
|
|
unsigned int reloc_type);
|
|
|
|
|
|
|
|
// Return the offset in the data section to which the next reloc
|
2010-12-02 03:49:22 +08:00
|
|
|
// applies. This returns -1 if there is no next reloc.
|
2007-11-09 15:00:15 +08:00
|
|
|
off_t
|
|
|
|
next_offset() const;
|
|
|
|
|
|
|
|
// Return the symbol index of the next reloc. This returns -1U if
|
|
|
|
// there is no next reloc.
|
|
|
|
unsigned int
|
|
|
|
next_symndx() const;
|
|
|
|
|
2010-12-02 03:49:22 +08:00
|
|
|
// Return the addend of the next reloc. This returns 0 if there is
|
|
|
|
// no next reloc.
|
|
|
|
uint64_t
|
|
|
|
next_addend() const;
|
|
|
|
|
2007-11-09 15:00:15 +08:00
|
|
|
// Advance to OFFSET within the data section, and return the number
|
|
|
|
// of relocs which would be skipped.
|
|
|
|
int
|
|
|
|
advance(off_t offset);
|
|
|
|
|
2012-03-22 03:02:22 +08:00
|
|
|
// Checkpoint the current position in the reloc section.
|
|
|
|
section_size_type
|
|
|
|
checkpoint() const
|
|
|
|
{ return this->pos_; }
|
|
|
|
|
|
|
|
// Reset the position to CHECKPOINT.
|
|
|
|
void
|
|
|
|
reset(section_size_type checkpoint)
|
|
|
|
{ this->pos_ = checkpoint; }
|
|
|
|
|
2007-11-09 15:00:15 +08:00
|
|
|
private:
|
2007-11-13 04:35:21 +08:00
|
|
|
// The contents of the input object's reloc section.
|
2007-11-09 15:00:15 +08:00
|
|
|
const unsigned char* prelocs_;
|
|
|
|
// The length of the reloc section.
|
2007-12-18 08:48:04 +08:00
|
|
|
section_size_type len_;
|
2007-11-09 15:00:15 +08:00
|
|
|
// Our current position in the reloc section.
|
2007-12-18 08:48:04 +08:00
|
|
|
section_size_type pos_;
|
2007-11-09 15:00:15 +08:00
|
|
|
// The size of the relocs in the section.
|
|
|
|
int reloc_size_;
|
|
|
|
};
|
|
|
|
|
2006-09-30 03:58:17 +08:00
|
|
|
} // End namespace gold.
|
|
|
|
|
|
|
|
#endif // !defined(GOLD_RELOC_H)
|