1/*
2    Title:     Export memory as an ELF object file
3    Author:    David C. J. Matthews.
4
5    Copyright (c) 2006, 2016-17 David C. J. Matthews
6
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public
10    License version 2.1 as published by the Free Software Foundation.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR H PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this library; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20*/
21
22#ifndef ELFExport_H_INCLUDED
23#define ELFExport_H_INCLUDED
24
25#include "config.h"
26
27#include "scanaddrs.h" // For base class
28#include "exporter.h"
29
30#ifdef HAVE_ELF_H
31#include <elf.h>
32#endif
33
34#ifdef HAVE_ELF_ABI_H
35#include <elf_abi.h>
36#endif
37
38// Select 32 or 64 bit version depending on the word length
39#if (SIZEOF_VOIDP == 8)
40#define ElfXX_Addr  Elf64_Addr
41#define ElfXX_Rel   Elf64_Rel
42#define ElfXX_Rela  Elf64_Rela
43#define ElfXX_Sym   Elf64_Sym
44#define ElfXX_Ehdr  Elf64_Ehdr
45#define ElfXX_Shdr  Elf64_Shdr
46// Include a cast on the next line.  Linux includes this anyway but it's needed for FreeBSD.
47#define ELFXX_R_INFO(_y, _z)    ELF64_R_INFO((Elf64_Xword)(_y), _z)
48#define ELFXX_ST_INFO(_y, _z)   ELF64_ST_INFO(_y, _z)
49#define ELFCLASSXX      ELFCLASS64
50#else
51#define ElfXX_Addr  Elf32_Addr
52#define ElfXX_Rel   Elf32_Rel
53#define ElfXX_Rela  Elf32_Rela
54#define ElfXX_Sym   Elf32_Sym
55#define ElfXX_Ehdr  Elf32_Ehdr
56#define ElfXX_Shdr  Elf32_Shdr
57#define ELFXX_R_INFO(_y, _z)    ELF32_R_INFO(_y, _z)
58#define ELFXX_ST_INFO(_y, _z)   ELF32_ST_INFO(_y, _z)
59#define ELFCLASSXX              ELFCLASS32
60#endif
61
62#ifdef HOSTARCHITECTURE_MIPS64
63/* MIPS N64 ABI has a different Elf64_Rel/Rela layout */
64
65typedef struct
66{
67  Elf64_Addr r_offset;      /* Address */
68  Elf64_Word r_sym;         /* Symbol index */
69  unsigned char r_ssym;     /* Special symbol */
70  unsigned char r_type3;    /* Third relocation type */
71  unsigned char r_type2;    /* Second relocation type */
72  unsigned char r_type;     /* First relocation type */
73} Elf64_Mips_Rel;
74
75typedef struct
76{
77  Elf64_Addr r_offset;      /* Address */
78  Elf64_Word r_sym;         /* Symbol index */
79  unsigned char r_ssym;     /* Special symbol */
80  unsigned char r_type3;    /* Third relocation type */
81  unsigned char r_type2;    /* Second relocation type */
82  unsigned char r_type;     /* First relocation type */
83  Elf64_Sxword r_addend;    /* Addend */
84} Elf64_Mips_Rela;
85
86#undef  ElfXX_Rel
87#define ElfXX_Rel   Elf64_Mips_Rel
88#undef  ElfXX_Rela
89#define ElfXX_Rela  Elf64_Mips_Rela
90/* Elf64_Mips_Rel/Rela has no r_info, so this macro is meaningless */
91#undef  ELFXX_R_INFO
92#endif
93
94class TaskData;
95
96class ELFExport: public Exporter, public ScanAddress
97{
98public:
99    ELFExport(): relocationCount(0), symbolNum(0) {}
100public:
101    virtual void exportStore(void);
102
103private:
104    // ScanAddress overrides
105    virtual void ScanConstant(PolyObject *base, byte *addrOfConst, ScanRelocationKind code);
106    // At the moment we should only get calls to ScanConstant.
107    virtual PolyObject *ScanObjectAddress(PolyObject *base) { return base; }
108    virtual void addExternalReference(void *addr, const char *name, bool isFuncPtr);
109
110private:
111    void setRelocationAddress(void *p, ElfXX_Addr *reloc);
112    PolyWord createRelocation(PolyWord p, void *relocAddr);
113    PolyWord writeRelocation(POLYUNSIGNED offset, void *relocAddr, unsigned symbolNum, bool isFuncPtr);
114    void writeSymbol(const char *symbolName, long value, long size, int binding, int sttype, int section);
115    unsigned long makeStringTableEntry(const char *str, ExportStringTable *stab);
116    void alignFile(int align);
117    void createStructsRelocation(unsigned area, size_t offset, size_t addend);
118
119    unsigned relocationCount;
120
121    // There are two tables - one is used for section names, the other for symbol names.
122    ExportStringTable symStrings, sectionStrings;
123    // Table and count for external references.
124    ExportStringTable externTable;
125    unsigned symbolNum;
126};
127
128#endif
129