OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [tools/] [src/] [lxp32asm/] [linkableobject.cpp] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 ring0_mipt
/*
2
 * Copyright (c) 2016 by Alex I. Kuznetsov.
3
 *
4
 * Part of the LXP32 CPU IP core.
5
 *
6
 * This module implements members of the LinkableObject class.
7
 */
8
 
9
#include "linkableobject.h"
10
#include "utils.h"
11
 
12
#include <iostream>
13
#include <fstream>
14
#include <stdexcept>
15
#include <utility>
16
#include <cassert>
17
#include <cstdlib>
18
 
19
std::string LinkableObject::name() const {
20
        return _name;
21
}
22
 
23
void LinkableObject::setName(const std::string &str) {
24
        _name=str;
25
}
26
 
27
LinkableObject::Word LinkableObject::virtualAddress() const {
28
        return _virtualAddress;
29
}
30
 
31
void LinkableObject::setVirtualAddress(Word addr) {
32
        _virtualAddress=addr;
33
}
34
 
35
LinkableObject::Byte *LinkableObject::code() {
36
        return _code.data();
37
}
38
 
39
const LinkableObject::Byte *LinkableObject::code() const {
40
        return _code.data();
41
}
42
 
43
std::size_t LinkableObject::codeSize() const {
44
        return _code.size();
45
}
46
 
47
LinkableObject::Word LinkableObject::addWord(Word w) {
48
        auto rva=addPadding(sizeof(Word));
49
// Note: this code doesn't depend on host machine's endianness
50
        _code.push_back(static_cast<Byte>(w));
51
        _code.push_back(static_cast<Byte>(w>>8));
52
        _code.push_back(static_cast<Byte>(w>>16));
53
        _code.push_back(static_cast<Byte>(w>>24));
54
        return rva;
55
}
56
 
57
LinkableObject::Word LinkableObject::addByte(Byte b) {
58
        auto rva=static_cast<LinkableObject::Word>(_code.size());
59
        _code.push_back(b);
60
        return rva;
61
}
62
 
63
LinkableObject::Word LinkableObject::addBytes(const Byte *p,std::size_t n) {
64
        auto rva=static_cast<LinkableObject::Word>(_code.size());
65
        _code.insert(_code.end(),p,p+n);
66
        return rva;
67
}
68
 
69
LinkableObject::Word LinkableObject::addZeros(std::size_t n) {
70
        auto rva=static_cast<LinkableObject::Word>(_code.size());
71
        _code.resize(_code.size()+n);
72
        return rva;
73
}
74
 
75
LinkableObject::Word LinkableObject::addPadding(std::size_t size) {
76
        auto padding=(size-_code.size()%size)%size;
77
        if(padding>0) _code.resize(_code.size()+padding);
78
        return static_cast<LinkableObject::Word>(_code.size());
79
}
80
 
81
LinkableObject::Word LinkableObject::getWord(Word rva) const {
82
        Word w=0;
83
        if(rva<codeSize()) w|=static_cast<Word>(_code[rva++]);
84
        if(rva<codeSize()) w|=static_cast<Word>(_code[rva++])<<8;
85
        if(rva<codeSize()) w|=static_cast<Word>(_code[rva++])<<16;
86
        if(rva<codeSize()) w|=static_cast<Word>(_code[rva++])<<24;
87
        return w;
88
}
89
 
90
void LinkableObject::replaceWord(Word rva,Word value) {
91
        assert(rva+sizeof(Word)<=codeSize());
92
// Note: this code doesn't depend on host machine's endianness
93
        _code[rva++]=static_cast<Byte>(value);
94
        _code[rva++]=static_cast<Byte>(value>>8);
95
        _code[rva++]=static_cast<Byte>(value>>16);
96
        _code[rva++]=static_cast<Byte>(value>>24);
97
}
98
 
99
void LinkableObject::addSymbol(const std::string &name,Word rva) {
100
        auto &data=symbol(name);
101
        if(data.type!=Unknown) throw std::runtime_error("Symbol \""+name+"\" is already defined");
102
        data.type=Local;
103
        data.rva=rva;
104
}
105
 
106
void LinkableObject::addImportedSymbol(const std::string &name) {
107
        auto &data=symbol(name);
108
        if(data.type!=Unknown) throw std::runtime_error("Symbol \""+name+"\" is already defined");
109
        data.type=Imported;
110
}
111
 
112
void LinkableObject::exportSymbol(const std::string &name) {
113
        auto it=_symbols.find(name);
114
        if(it==_symbols.end()||it->second.type==Unknown) throw std::runtime_error("Undefined symbol \""+name+"\"");
115
        if(it->second.type==Imported) throw std::runtime_error("Symbol \""+name+"\" can't be both imported and exported at the same time");
116
        if(it->second.type==Exported) throw std::runtime_error("Symbol \""+name+"\" has been already exported");
117
        it->second.type=Exported;
118
}
119
 
120
void LinkableObject::addReference(const std::string &symbolName,const Reference &ref) {
121
        auto &data=symbol(symbolName);
122
        data.refs.push_back(ref);
123
}
124
 
125
LinkableObject::SymbolData &LinkableObject::symbol(const std::string &name) {
126
        return _symbols[name];
127
}
128
 
129
const LinkableObject::SymbolData &LinkableObject::symbol(const std::string &name) const {
130
        auto const it=_symbols.find(name);
131
        if(it==_symbols.end()) throw std::runtime_error("Undefined symbol \""+name+"\"");
132
        return it->second;
133
}
134
 
135
const LinkableObject::SymbolTable &LinkableObject::symbols() const {
136
        return _symbols;
137
}
138
 
139
void LinkableObject::serialize(const std::string &filename) const {
140
        std::ofstream out(filename,std::ios_base::out);
141
        if(!out) throw std::runtime_error("Cannot open \""+filename+"\" for writing");
142
 
143
        out<<"LinkableObject"<<std::endl;
144
        if(!_name.empty()) out<<"Name "<<Utils::urlEncode(_name)<<std::endl;
145
        out<<"VirtualAddress 0x"<<Utils::hex(_virtualAddress)<<std::endl;
146
 
147
        out<<std::endl;
148
        out<<"Start Code"<<std::endl;
149
 
150
        for(Word rva=0;rva<_code.size();rva+=sizeof(Word)) {
151
                out<<"\t0x"<<Utils::hex(getWord(rva))<<std::endl;
152
        }
153
 
154
        out<<"End Code"<<std::endl;
155
 
156
        for(auto const &sym: _symbols) {
157
                if(sym.second.type==Unknown)
158
                        throw std::runtime_error("Undefined symbol: \""+sym.first+"\"");
159
                out<<std::endl;
160
                out<<"Start Symbol"<<std::endl;
161
                out<<"\tName "<<Utils::urlEncode(sym.first)<<std::endl;
162
                if(sym.second.type==Local) out<<"\tType Local"<<std::endl;
163
                else if(sym.second.type==Exported) out<<"\tType Exported"<<std::endl;
164
                else out<<"\tType Imported"<<std::endl;
165
                if(sym.second.type!=Imported) out<<"\tRVA 0x"<<Utils::hex(sym.second.rva)<<std::endl;
166
                for(auto const &ref: sym.second.refs) {
167
                        out<<"\tRef ";
168
                        out<<Utils::urlEncode(ref.source)<<" ";
169
                        out<<ref.line<<" ";
170
                        out<<"0x"<<Utils::hex(ref.rva)<<" ";
171
                        out<<ref.offset<<" ";
172
                        if(ref.type==Regular) out<<"Regular"<<std::endl;
173
                        else if(ref.type==Short) out<<"Short"<<std::endl;
174
                }
175
                out<<"End Symbol"<<std::endl;
176
        }
177
}
178
 
179
void LinkableObject::deserialize(const std::string &filename) {
180
        std::ifstream in(filename,std::ios_base::in);
181
        if(!in) throw std::runtime_error("Cannot open \""+filename+"\"");
182
 
183
        operator=(LinkableObject());
184
 
185
        std::string line;
186
        for(;;) {
187
                if(!std::getline(in,line)) throw std::runtime_error("Bad object format");
188
                auto tokens=tokenize(line);
189
                if(tokens.empty()) continue;
190
                else if(tokens[0]!="LinkableObject") throw std::runtime_error("Bad object format");
191
                break;
192
        }
193
 
194
        while(std::getline(in,line)) {
195
                auto tokens=tokenize(line);
196
                if(tokens.empty()) continue;
197
                if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
198
                else if(tokens[0]=="Name") _name=Utils::urlDecode(tokens[1]);
199
                else if(tokens[0]=="VirtualAddress") _virtualAddress=std::strtoul(tokens[1].c_str(),NULL,0);
200
                else if(tokens[0]=="Start") {
201
                        if(tokens[1]=="Code") deserializeCode(in);
202
                        else if(tokens[1]=="Symbol") deserializeSymbol(in);
203
                        else throw std::runtime_error("Unexpected token: \""+tokens[1]+"\"");
204
                }
205
                else throw std::runtime_error("Unexpected token: \""+tokens[0]+"\"");
206
        }
207
}
208
 
209
/*
210
 * Private members
211
 */
212
 
213
void LinkableObject::deserializeCode(std::istream &in) {
214
        std::string line;
215
        while(std::getline(in,line)) {
216
                auto tokens=tokenize(line);
217
                if(tokens.empty()) continue;
218
                if(tokens[0]=="End") {
219
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
220
                        if(tokens[1]=="Code") return;
221
                        throw std::runtime_error("Unexpected token: \""+tokens[1]+"\"");
222
                }
223
                auto w=static_cast<Word>(std::strtoul(tokens[0].c_str(),NULL,0));
224
                addWord(w);
225
        }
226
        throw std::runtime_error("Unexpected end of file");
227
}
228
 
229
void LinkableObject::deserializeSymbol(std::istream &in) {
230
        std::string line;
231
        std::string name;
232
        SymbolData data;
233
        while(std::getline(in,line)) {
234
                auto tokens=tokenize(line);
235
                if(tokens.empty()) continue;
236
                if(tokens[0]=="End") {
237
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
238
                        if(tokens[1]=="Symbol") {
239
                                if(name.empty()) throw std::runtime_error("Symbol name is not defined");
240
                                if(data.type==Unknown) throw std::runtime_error("Bad symbol type");
241
                                _symbols.emplace(std::move(name),std::move(data));
242
                                return;
243
                        }
244
                        throw std::runtime_error("Unexpected token: \""+tokens[1]+"\"");
245
                }
246
                else if(tokens[0]=="Name") {
247
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
248
                        name=Utils::urlDecode(tokens[1]);
249
                }
250
                else if(tokens[0]=="Type") {
251
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
252
                        if(tokens[1]=="Local") data.type=Local;
253
                        else if(tokens[1]=="Exported") data.type=Exported;
254
                        else if(tokens[1]=="Imported") data.type=Imported;
255
                        else throw std::runtime_error("Bad symbol type");
256
                }
257
                else if(tokens[0]=="RVA") {
258
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
259
                        data.rva=std::strtoul(tokens[1].c_str(),NULL,0);
260
                }
261
                else if(tokens[0]=="Ref") {
262
                        Reference ref;
263
                        if(tokens.size()<4) throw std::runtime_error("Unexpected end of line");
264
                        ref.source=Utils::urlDecode(tokens[1]);
265
                        ref.line=std::strtoul(tokens[2].c_str(),NULL,0);
266
                        ref.rva=std::strtoul(tokens[3].c_str(),NULL,0);
267
                        ref.offset=std::strtoll(tokens[4].c_str(),NULL,0);
268
                        if(tokens[5]=="Regular") ref.type=Regular;
269
                        else if(tokens[5]=="Short") ref.type=Short;
270
                        else throw std::runtime_error("Invalid reference type: \""+tokens[5]+"\"");
271
                        data.refs.push_back(std::move(ref));
272
                }
273
        }
274
        throw std::runtime_error("Unexpected end of file");
275
}
276
 
277
std::vector<std::string> LinkableObject::tokenize(const std::string &str) {
278
        std::vector<std::string> tokens;
279
        for(std::size_t pos=0;;) {
280
                auto start=str.find_first_not_of(" \t\r\n",pos);
281
                if(start==std::string::npos) return tokens;
282
                auto end=str.find_first_of(" \t\r\n",start);
283
                if(end==std::string::npos) {
284
                        tokens.push_back(str.substr(start));
285
                        return tokens;
286
                }
287
                else tokens.push_back(str.substr(start,end-start));
288
                pos=end;
289
        }
290
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.