Skip to content

Commit ec2c312

Browse files
committed
unittests for mapfile reading
1 parent e9caf5c commit ec2c312

8 files changed

+1430
-0
lines changed

Diff for: lib/map-file-delphi.js

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// Copyright (c) 2017, Compiler Explorer Authors
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright notice,
8+
// 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+
//
13+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23+
// POSSIBILITY OF SUCH DAMAGE.
24+
"use strict";
25+
26+
const MapFileReader = require("./map-file").MapFileReader;
27+
28+
class MapFileReaderDelphi extends MapFileReader {
29+
/**
30+
* constructor
31+
* @param {string} mapFilename
32+
*/
33+
constructor(mapFilename) {
34+
super(mapFilename);
35+
36+
this.regexDelphiCodeSegmentOffset = /^\s([0-9a-f]*):([0-9a-f]*)\s*([0-9a-f]*)H\s*(\.[a-z$]*)\s*([a-z]*)$/i;
37+
this.regexDelphiCodeSegment = /^\s([0-9a-f]*):([0-9a-f]*)\s*([0-9a-f]*)\s*C=CODE\s*S=.text\s*G=.*M=([\w\d.]*)\s.*/i;
38+
this.regexDelphiICodeSegment = /^\s([0-9a-f]*):([0-9a-f]*)\s*([0-9a-f]*)\s*C=ICODE\s*S=.itext\s*G=.*M=([\w\d.]*)\s.*/i;
39+
this.regexDelphiNames = /^\s([0-9a-f]*):([0-9a-f]*)\s*([a-z0-9_@$.<>{}]*)$/i;
40+
this.regexDelphiLineNumbersStart = /Line numbers for (.*)\(.*\) segment \.text/i;
41+
this.regexDelphiLineNumber = /^([0-9]*)\s([0-9a-f]*):([0-9a-f]*)/i;
42+
this.regexDelphiLineNumbersStartIText = /Line numbers for (.*)\(.*\) segment \.itext/i;
43+
}
44+
45+
/**
46+
* Tries to match the given line to code segment information
47+
* Matches in order:
48+
* 1. segment offset info
49+
* 2. code segment delphi map
50+
* 3. icode segment delphi map
51+
* 4. code segment vs map
52+
* @param {string} line
53+
*/
54+
tryReadingCodeSegmentInfo(line) {
55+
let codesegmentObject = false;
56+
57+
let matches = line.match(this.regexDelphiCodeSegmentOffset);
58+
if (matches && !matches[4].includes('$') && (parseInt(matches[2], 16) >= this.preferredLoadAddress)) {
59+
const addressWithOffset = parseInt(matches[2], 16);
60+
this.segmentOffsets.push({
61+
segment: matches[1],
62+
addressInt: addressWithOffset,
63+
address: addressWithOffset.toString(16),
64+
segmentLength: parseInt(matches[3], 16)
65+
});
66+
} else {
67+
matches = line.match(this.regexDelphiCodeSegment);
68+
if (matches) {
69+
codesegmentObject = this.addressToObject(matches[1], matches[2]);
70+
codesegmentObject.id = this.segments.length + 1;
71+
codesegmentObject.segmentLength = parseInt(matches[3], 16);
72+
codesegmentObject.unitName = matches[4];
73+
74+
this.segments.push(codesegmentObject);
75+
} else {
76+
matches = line.match(this.regexDelphiICodeSegment);
77+
if (matches) {
78+
codesegmentObject = this.addressToObject(matches[1], matches[2]);
79+
codesegmentObject.id = this.isegments.length + 1;
80+
codesegmentObject.segmentLength = parseInt(matches[3], 16);
81+
codesegmentObject.unitName = matches[4];
82+
83+
this.isegments.push(codesegmentObject);
84+
}
85+
}
86+
}
87+
}
88+
89+
/**
90+
* Try to match information about the address where a symbol is
91+
* @param {string} line
92+
*/
93+
tryReadingNamedAddress(line) {
94+
let symbolObject = false;
95+
96+
const matches = line.match(this.regexDelphiNames);
97+
if (matches) {
98+
if (!this.getSymbolInfoByName(matches[3])) {
99+
symbolObject = this.addressToObject(matches[1], matches[2]);
100+
symbolObject.displayName = matches[3];
101+
102+
this.namedAddresses.push(symbolObject);
103+
}
104+
}
105+
}
106+
107+
/**
108+
*
109+
* @param {string} line
110+
*/
111+
isStartOfLineNumbers(line) {
112+
const matches = line.match(this.regexDelphiLineNumbersStart);
113+
if (matches) {
114+
return true;
115+
}
116+
117+
return false;
118+
}
119+
120+
/**
121+
* Retreives line number references from supplied Map line
122+
* @param {string} line
123+
* @returns {boolean}
124+
*/
125+
tryReadingLineNumbers(line) {
126+
let hasLineNumbers = false;
127+
128+
const references = line.split(" "); // 4 spaces
129+
for (let refIdx = 0; refIdx < references.length; refIdx++) {
130+
const matches = references[refIdx].match(this.regexDelphiLineNumber);
131+
if (matches) {
132+
const lineObject = this.addressToObject(matches[2], matches[3]);
133+
lineObject.lineNumber = parseInt(matches[1], 10);
134+
135+
this.lineNumbers.push(lineObject);
136+
137+
hasLineNumbers = true;
138+
}
139+
}
140+
141+
return hasLineNumbers;
142+
}
143+
}
144+
145+
exports.MapFileReader = MapFileReaderDelphi;

0 commit comments

Comments
 (0)