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

Subversion Repositories lxp32

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 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::addLocalSymbol(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::addExternalSymbol(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=External;
110
}
111
 
112
void LinkableObject::addReference(const std::string &symbolName,const std::string &source,int line,Word rva) {
113
        auto &data=symbol(symbolName);
114
        data.refs.push_back({source,line,rva});
115
}
116
 
117
LinkableObject::SymbolData &LinkableObject::symbol(const std::string &name) {
118
        return _symbols[name];
119
}
120
 
121
const LinkableObject::SymbolData &LinkableObject::symbol(const std::string &name) const {
122
        auto const it=_symbols.find(name);
123
        if(it==_symbols.end()) throw std::runtime_error("Undefined symbol");
124
        return it->second;
125
}
126
 
127
const LinkableObject::SymbolTable &LinkableObject::symbols() const {
128
        return _symbols;
129
}
130
 
131
void LinkableObject::serialize(const std::string &filename) const {
132
        std::ofstream out(filename,std::ios_base::out);
133
        if(!out) throw std::runtime_error("Cannot open \""+filename+"\" for writing");
134
 
135
        out<<"LinkableObject"<<std::endl;
136
        if(!_name.empty()) out<<"Name "<<Utils::urlEncode(_name)<<std::endl;
137
        out<<"VirtualAddress 0x"<<Utils::hex(_virtualAddress)<<std::endl;
138
 
139
        out<<std::endl;
140
        out<<"Start Code"<<std::endl;
141
 
142
        for(Word rva=0;rva<_code.size();rva+=sizeof(Word)) {
143
                out<<"\t0x"<<Utils::hex(getWord(rva))<<std::endl;
144
        }
145
 
146
        out<<"End Code"<<std::endl;
147
 
148
        for(auto const &sym: _symbols) {
149
                if(sym.second.type==Unknown)
150
                        throw std::runtime_error("Undefined symbol: \""+sym.first+"\"");
151
                out<<std::endl;
152
                out<<"Start Symbol"<<std::endl;
153
                out<<"\tName "<<Utils::urlEncode(sym.first)<<std::endl;
154
                if(sym.second.type==Local) out<<"\tRVA 0x"<<Utils::hex(sym.second.rva)<<std::endl;
155
                else out<<"\tExternal"<<std::endl;
156
                for(auto const &ref: sym.second.refs) {
157
                        out<<"\tRef "<<Utils::urlEncode(ref.source)<<" "<<ref.line<<" 0x"<<Utils::hex(ref.rva)<<std::endl;
158
                }
159
                out<<"End Symbol"<<std::endl;
160
        }
161
}
162
 
163
void LinkableObject::deserialize(const std::string &filename) {
164
        std::ifstream in(filename,std::ios_base::in);
165
        if(!in) throw std::runtime_error("Cannot open \""+filename+"\"");
166
 
167
        operator=(LinkableObject());
168
 
169
        std::string line;
170
        for(;;) {
171
                if(!std::getline(in,line)) throw std::runtime_error("Bad object format");
172
                auto tokens=tokenize(line);
173
                if(tokens.empty()) continue;
174
                else if(tokens[0]!="LinkableObject") throw std::runtime_error("Bad object format");
175
                break;
176
        }
177
 
178
        while(std::getline(in,line)) {
179
                auto tokens=tokenize(line);
180
                if(tokens.empty()) continue;
181
                if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
182
                else if(tokens[0]=="Name") _name=Utils::urlDecode(tokens[1]);
183
                else if(tokens[0]=="VirtualAddress") _virtualAddress=std::strtoul(tokens[1].c_str(),NULL,0);
184
                else if(tokens[0]=="Start") {
185
                        if(tokens[1]=="Code") deserializeCode(in);
186
                        else if(tokens[1]=="Symbol") deserializeSymbol(in);
187
                        else throw std::runtime_error("Unexpected token: \""+tokens[1]+"\"");
188
                }
189
                else throw std::runtime_error("Unexpected token: \""+tokens[0]+"\"");
190
        }
191
}
192
 
193
/*
194
 * Private members
195
 */
196
 
197
void LinkableObject::deserializeCode(std::istream &in) {
198
        std::string line;
199
        while(std::getline(in,line)) {
200
                auto tokens=tokenize(line);
201
                if(tokens.empty()) continue;
202
                if(tokens[0]=="End") {
203
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
204
                        if(tokens[1]=="Code") return;
205
                        throw std::runtime_error("Unexpected token: \""+tokens[1]+"\"");
206
                }
207
                auto w=static_cast<Word>(std::strtoul(tokens[0].c_str(),NULL,0));
208
                addWord(w);
209
        }
210
        throw std::runtime_error("Unexpected end of file");
211
}
212
 
213
void LinkableObject::deserializeSymbol(std::istream &in) {
214
        std::string line;
215
        std::string name;
216
        SymbolData data;
217
        while(std::getline(in,line)) {
218
                auto tokens=tokenize(line);
219
                if(tokens.empty()) continue;
220
                if(tokens[0]=="End") {
221
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
222
                        if(tokens[1]=="Symbol") {
223
                                if(name.empty()) throw std::runtime_error("Symbol name is not defined");
224
                                if(data.type==Unknown) throw std::runtime_error("Bad symbol type");
225
                                _symbols.emplace(std::move(name),std::move(data));
226
                                return;
227
                        }
228
                        throw std::runtime_error("Unexpected token: \""+tokens[1]+"\"");
229
                }
230
                else if(tokens[0]=="Name") {
231
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
232
                        name=Utils::urlDecode(tokens[1]);
233
                }
234
                else if(tokens[0]=="External") data.type=External;
235
                else if(tokens[0]=="RVA") {
236
                        if(tokens.size()<2) throw std::runtime_error("Unexpected end of line");
237
                        data.type=Local;
238
                        data.rva=std::strtoul(tokens[1].c_str(),NULL,0);
239
                }
240
                else if(tokens[0]=="Ref") {
241
                        Reference ref;
242
                        if(tokens.size()<4) throw std::runtime_error("Unexpected end of line");
243
                        ref.source=Utils::urlDecode(tokens[1]);
244
                        ref.line=std::strtoul(tokens[2].c_str(),NULL,0);
245
                        ref.rva=std::strtoul(tokens[3].c_str(),NULL,0);
246
                        data.refs.push_back(std::move(ref));
247
                }
248
        }
249
        throw std::runtime_error("Unexpected end of file");
250
}
251
 
252
std::vector<std::string> LinkableObject::tokenize(const std::string &str) {
253
        std::vector<std::string> tokens;
254
        for(std::size_t pos=0;;) {
255
                auto start=str.find_first_not_of(" \t\r\n",pos);
256
                if(start==std::string::npos) return tokens;
257
                auto end=str.find_first_of(" \t\r\n",start);
258
                if(end==std::string::npos) {
259
                        tokens.push_back(str.substr(start));
260
                        return tokens;
261
                }
262
                else tokens.push_back(str.substr(start,end-start));
263
                pos=end;
264
        }
265
}

powered by: WebSVN 2.1.0

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