1/*
2 * Copyright (c) 2002-2004 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 *          Steve Reinhardt
30 */
31
32#ifndef __OBJECT_FILE_HH__
33#define __OBJECT_FILE_HH__
34
35#include <limits>
36#include <string>
37
38#include "base/logging.hh"
39#include "base/types.hh"
40
41class PortProxy;
42class Process;
43class ProcessParams;
44class SymbolTable;
45
46class ObjectFile
47{
48  public:
49
50    enum Arch {
51        UnknownArch,
52        Alpha,
53        SPARC64,
54        SPARC32,
55        Mips,
56        X86_64,
57        I386,
58        Arm64,
59        Arm,
60        Thumb,
61        Power,
62        Riscv64,
63        Riscv32
64    };
65
66    enum OpSys {
67        UnknownOpSys,
68        Tru64,
69        Linux,
70        Solaris,
71        LinuxArmOABI,
72        FreeBSD
73    };
74
75  protected:
76    const std::string filename;
77    uint8_t *fileData;
78    size_t len;
79
80    Arch arch;
81    OpSys opSys;
82
83    ObjectFile(const std::string &_filename, size_t _len, uint8_t *_data,
84               Arch _arch, OpSys _opSys);
85
86  public:
87    virtual ~ObjectFile();
88
89    static const Addr maxAddr = std::numeric_limits<Addr>::max();
90
91    virtual bool loadSections(const PortProxy& mem_proxy,
92                              Addr mask = maxAddr, Addr offset = 0);
93
94    virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
95                                Addr offset = 0, Addr mask = maxAddr) = 0;
96    virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
97                                   Addr offset = 0, Addr mask = maxAddr) = 0;
98    virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0,
99                                  Addr offset = 0, Addr mask = maxAddr) = 0;
100    virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base = 0,
101                                 Addr offset = 0, Addr mask = maxAddr)
102    { return false; }
103
104    virtual ObjectFile *getInterpreter() const { return nullptr; }
105    virtual bool relocatable() const { return false; }
106    virtual Addr mapSize() const
107    { panic("mapSize() should only be called on relocatable objects\n"); }
108    virtual void updateBias(Addr bias_addr)
109    { panic("updateBias() should only be called on relocatable objects\n"); }
110    virtual Addr bias() const { return 0; }
111
112    virtual bool hasTLS() { return false; }
113
114    Arch  getArch()  const { return arch; }
115    OpSys getOpSys() const { return opSys; }
116
117  protected:
118
119    struct Section {
120        Addr baseAddr;
121        uint8_t *fileImage;
122        size_t size;
123    };
124
125    Addr entry;
126    Addr globalPtr;
127
128    Section text;
129    Section data;
130    Section bss;
131
132    bool loadSection(Section *sec, const PortProxy& mem_proxy, Addr mask,
133                     Addr offset = 0);
134    void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; }
135
136  public:
137    Addr entryPoint() const { return entry; }
138
139    Addr globalPointer() const { return globalPtr; }
140
141    Addr textBase() const { return text.baseAddr; }
142    Addr dataBase() const { return data.baseAddr; }
143    Addr bssBase() const { return bss.baseAddr; }
144
145    size_t textSize() const { return text.size; }
146    size_t dataSize() const { return data.size; }
147    size_t bssSize() const { return bss.size; }
148
149    /* This function allows you to override the base address where
150     * a binary is going to be loaded or set it if the binary is just a
151     * blob that doesn't include an object header.
152     * @param a address to load the binary/text section at
153     */
154    void setTextBase(Addr a) { text.baseAddr = a; }
155
156    /**
157     * Each instance of a Loader subclass will have a chance to try to load
158     * an object file when tryLoaders is called. If they can't because they
159     * aren't compatible with it (wrong arch, wrong OS, etc), then they
160     * silently fail by returning nullptr so other loaders can try.
161     */
162    class Loader
163    {
164      public:
165        Loader();
166
167        /* Loader instances are singletons. */
168        Loader(const Loader &) = delete;
169        void operator=(const Loader &) = delete;
170
171        virtual ~Loader() {}
172
173        /**
174         * Each subclass needs to implement this method. If the loader is
175         * compatible with the passed in object file, it should return the
176         * created Process object corresponding to it. If not, it should fail
177         * silently and return nullptr. If there's a non-compatibliity related
178         * error like file IO errors, etc., those should fail non-silently
179         * with a panic or fail as normal.
180         */
181        virtual Process *load(ProcessParams *params, ObjectFile *obj_file) = 0;
182    };
183
184    // Try all the Loader instance's "load" methods one by one until one is
185    // successful. If none are, complain and fail.
186    static Process *tryLoaders(ProcessParams *params, ObjectFile *obj_file);
187};
188
189ObjectFile *createObjectFile(const std::string &fname, bool raw = false);
190
191
192#endif // __OBJECT_FILE_HH__
193