Skip to content

Commit d4fb840

Browse files
committed
Support section names + start/end modifiers
Both as matching and patch arguments. E.g.: .text .text.start .text.end ".text".start etc. Fix GJDuck#61
1 parent 507b696 commit d4fb840

9 files changed

Lines changed: 107 additions & 17 deletions

File tree

src/e9tool/e9action.cpp

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,21 @@ static intptr_t parseIndex(Parser &parser, intptr_t lb, intptr_t ub)
7979
*/
8080
static intptr_t parseSymbol(Parser &parser, const char *symbol)
8181
{
82-
intptr_t val = getELFObject(parser.elf, symbol);
82+
bool end = false;
83+
if (parser.peekToken() == '.')
84+
{
85+
parser.getToken();
86+
switch (parser.getToken())
87+
{
88+
case TOKEN_START:
89+
break;
90+
case TOKEN_END:
91+
end = true; break;
92+
default:
93+
parser.unexpectedToken();
94+
}
95+
}
96+
intptr_t val = getELFObject(parser.elf, symbol, end);
8397
if (val == -1)
8498
{
8599
warning("symbol \"%s\" is undefined and therefore has value 0x0",
@@ -292,10 +306,27 @@ static const MatchArg parseMatchArg(Parser &parser, bool val = false)
292306
error("failed to parse regular expression \"%s\"", parser.s);
293307
}
294308
case '&':
309+
{
295310
if (parser.peekToken() == TOKEN_MEM)
296311
break;
297-
parser.expectToken2(TOKEN_STRING, TOKEN_NAME);
298-
return MatchArg(new MatchVal(parseSymbol(parser, parser.s)));
312+
std::string name;
313+
switch (parser.getToken())
314+
{
315+
case '.':
316+
name += '.';
317+
parser.expectToken(TOKEN_NAME);
318+
// Fallthrough:
319+
case TOKEN_NAME:
320+
name += parser.s;
321+
break;
322+
case TOKEN_STRING:
323+
name += parser.s;
324+
break;
325+
default:
326+
parser.unexpectedToken();
327+
}
328+
return MatchArg(new MatchVal(parseSymbol(parser, name.c_str())));
329+
}
299330
case TOKEN_NIL:
300331
return MatchArg(new MatchVal(nullptr));
301332
case '-':
@@ -823,6 +854,28 @@ static const char *parseFunctionName(Parser &parser)
823854
return strDup(parser.s);
824855
}
825856

857+
/*
858+
* Parse a name.
859+
*/
860+
static const char *parseSymbolName(Parser &parser, int t, bool ptr)
861+
{
862+
std::string name;
863+
switch (t)
864+
{
865+
case '.':
866+
name += '.';
867+
parser.expectToken(TOKEN_NAME);
868+
name += parser.s;
869+
return strDup(name.c_str());
870+
case TOKEN_NAME:
871+
return strDup(parser.s);
872+
case TOKEN_STRING:
873+
return (ptr? strDup(parser.s): nullptr);
874+
default:
875+
return nullptr;
876+
}
877+
}
878+
826879
/*
827880
* Parse a patch.
828881
*/
@@ -970,7 +1023,7 @@ const Patch *parsePatch(const ELF &elf, const char *str)
9701023
parser.expectToken(')');
9711024
t = parser.getToken();
9721025
}
973-
bool ptr = false, neg = false;
1026+
bool ptr = false, end = false, neg = false;
9741027
if (t == '&')
9751028
{
9761029
ptr = true;
@@ -982,7 +1035,9 @@ const Patch *parsePatch(const ELF &elf, const char *str)
9821035
1, 0};
9831036
intptr_t value = 0x0;
9841037
int arg_token = t;
985-
const char *name = nullptr;
1038+
const char *name = parseSymbolName(parser, t, ptr);
1039+
if (name != nullptr)
1040+
t = TOKEN_NAME;
9861041
switch (t)
9871042
{
9881043
case TOKEN_ASM:
@@ -1073,7 +1128,6 @@ const Patch *parsePatch(const ELF &elf, const char *str)
10731128
ARGUMENT_STRING);
10741129
break;
10751130
case TOKEN_NAME:
1076-
name = strDup(parser.s);
10771131
arg = (parser.peekToken() == '['? ARGUMENT_CSV:
10781132
ARGUMENT_SYMBOL);
10791133
break;
@@ -1155,11 +1209,22 @@ const Patch *parsePatch(const ELF &elf, const char *str)
11551209
}
11561210
}
11571211
break;
1158-
case ARGUMENT_STRING:
1159-
if (ptr)
1160-
arg = ARGUMENT_SYMBOL;
1212+
case ARGUMENT_SYMBOL:
1213+
if (parser.peekToken() == '.')
1214+
{
1215+
parser.getToken();
1216+
switch (parser.getToken())
1217+
{
1218+
case TOKEN_START:
1219+
break;
1220+
case TOKEN_END:
1221+
end = true; break;
1222+
default:
1223+
parser.unexpectedToken();
1224+
}
1225+
}
11611226
break;
1162-
case ARGUMENT_MEMOP: case ARGUMENT_SYMBOL:
1227+
case ARGUMENT_MEMOP:
11631228
break;
11641229
case ARGUMENT_REGISTER:
11651230
if ((Register)value == REGISTER_RIP)
@@ -1200,7 +1265,7 @@ const Patch *parsePatch(const ELF &elf, const char *str)
12001265
break;
12011266
}
12021267
}
1203-
args.push_back({arg, field, ptr, _static, duplicate, cast,
1268+
args.push_back({arg, field, ptr, end, _static, duplicate, cast,
12041269
value, memop, name});
12051270
t = parser.getToken();
12061271
if (t == ')')

src/e9tool/e9frontend.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,12 +1570,13 @@ extern const PLTInfo &e9tool::getELFPLTInfo(const ELF *elf)
15701570
/*
15711571
* Find the address associated with the given name.
15721572
*/
1573-
intptr_t e9tool::getELFObject(const ELF *elf, const char *name)
1573+
intptr_t e9tool::getELFObject(const ELF *elf, const char *name, bool end)
15741574
{
15751575
// CASE #1: section
15761576
const Elf64_Shdr *shdr = getELFSection(elf, name);
15771577
if (shdr != nullptr)
1578-
return elf->base + (intptr_t)shdr->sh_addr;
1578+
return elf->base + (intptr_t)shdr->sh_addr +
1579+
(end? (intptr_t)shdr->sh_size: 0);
15791580

15801581
// CASE #2: symbol
15811582
const Elf64_Sym *sym = getELFDynSym(elf, name);

src/e9tool/e9metadata.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,7 +1677,7 @@ static Type sendLoadArgumentMetadata(FILE *out, CallInfo &info,
16771677
case ARGUMENT_SYMBOL:
16781678
{
16791679
t = TYPE_CONST | TYPE_VOID | TYPE_PTR;
1680-
intptr_t val = getELFObject(elf, arg.name);
1680+
intptr_t val = getELFObject(elf, arg.name, arg.end);
16811681
if (val == -1)
16821682
{
16831683
warning(CONTEXT_FORMAT "failed to load ELF object into "
@@ -2202,7 +2202,7 @@ void e9tool::sendCallMetadata(FILE *out, const char *name, const ELF *elf,
22022202
* Build metadata.
22032203
*/
22042204
void sendMetadata(FILE *out, const ELF *elf, const Action *action, size_t idx,
2205-
const std::vector<Instr> &Is, size_t i, const InstrInfo *I, intptr_t id,
2205+
const std::vector<Instr> &Is, size_t i, const InstrInfo *I, intptr_t id,
22062206
Context *cxt)
22072207
{
22082208
if (action == nullptr)

src/e9tool/e9metadata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "e9tool.h"
2727

2828
extern void sendMetadata(FILE *out, const e9tool::ELF *elf,
29-
const Action *action, size_t idx, const std::vector<e9tool::Instr> &Is,
29+
const Action *action, size_t idx, const std::vector<e9tool::Instr> &Is,
3030
size_t i, const e9tool::InstrInfo *I, intptr_t id, Context *cxt);
3131

3232
#endif

src/e9tool/e9tool.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,7 @@ struct Argument
23382338
ArgumentKind kind; // Argument kind.
23392339
FieldKind field; // Argument field.
23402340
bool ptr; // Argument is passed by pointer?
2341+
bool end; // Argument ptr to the end of object?
23412342
bool _static; // Argument is static?
23422343
bool duplicate; // Argument is a duplicate?
23432344
Type cast; // Argument type cast.
@@ -2458,7 +2459,8 @@ extern const SymbolInfo &getELFDynSymInfo(const ELF *elf);
24582459
extern const SymbolInfo &getELFSymInfo(const ELF *elf);
24592460
extern const GOTInfo &getELFGOTInfo(const ELF *elf);
24602461
extern const PLTInfo &getELFPLTInfo(const ELF *elf);
2461-
extern intptr_t getELFObject(const ELF *elf, const char *name);
2462+
extern intptr_t getELFObject(const ELF *elf, const char *name,
2463+
bool end = false);
24622464

24632465
// Note: Windows PE files are parsed as "pseudo-ELF" files. This saves having
24642466
// to rewrite/redesign large parts of E9Tool. This may change in future.

test/regtest/section_name_end.exp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
2+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
3+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
4+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
5+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
6+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
7+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
8+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
9+
.text=0xa000000..0xa000333 [0xa000333,0xa000333]
10+
PASSED

test/regtest/section_name_end.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./test -M sib -P 'format(".text=%p..%p [%p,%p]\n",.text.start,.text.end,&.text.end,&".text".end)@patch'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
jmpq *0x777f(%rsp,%rcx,1)
2+
movq -0x100(%rsp), %rax
3+
movq -0x100(%rsp,%rsi,8), %rax
4+
movq -0x100(%rsp,%rsi,8), %rax
5+
movq %gs:-0x100(%rsp,%rsi,8), %rcx
6+
movl 0xa000000, %ecx
7+
movq 0xa000000(%rax,%rsi,8), %rcx
8+
movq 0xa000000(,%rsi,8), %rdx
9+
movq 0xa000008, %rdx
10+
PASSED

test/regtest/section_name_match.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./test -M 'sib && &.text == 0xa000000 && &".text" == 0xa000000 && &.text.start == 0xa000000 && &.text.end == 0xa000333 && &".text".end == 0xa000333' -P print

0 commit comments

Comments
 (0)