Skip to content

Commit faa6bc1

Browse files
Merge branch 'dev' into issue2230
2 parents 62283ee + 37dc845 commit faa6bc1

20 files changed

Lines changed: 486 additions & 117 deletions

.github/dependabot.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: 2
2+
3+
updates:
4+
- package-ecosystem: github-actions
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ jobs:
160160
gcc-12 \
161161
g++-12
162162
fi
163-
- uses: actions/setup-python@v5
163+
- uses: actions/setup-python@v6
164164
if: matrix.system-deps == false
165165
with:
166166
python-version: ${{ matrix.python-version }}
@@ -283,7 +283,7 @@ jobs:
283283
echo PACKAGE_NAME=Cutter-${PACKAGE_ID}-src.tar.gz >> $GITHUB_ENV
284284
echo PACKAGE_PATH=Cutter-${PACKAGE_ID}-src.tar.gz >> $GITHUB_ENV
285285
echo UPLOAD_ASSET_TYPE=application/gzip >> $GITHUB_ENV
286-
- uses: actions/upload-artifact@v4
286+
- uses: actions/upload-artifact@v7
287287
if: env.PACKAGE_NAME != null
288288
with:
289289
name: ${{ env.PACKAGE_NAME }}
@@ -368,7 +368,7 @@ jobs:
368368
qt-major: ${{ matrix.qt-major }}
369369
package: ${{ matrix.package }}
370370

371-
- uses: actions/upload-artifact@v4
371+
- uses: actions/upload-artifact@v7
372372
if: env.PACKAGE_NAME != null
373373
with:
374374
name: ${{ steps.build.outputs.PACKAGE_NAME }}
@@ -426,7 +426,7 @@ jobs:
426426
with:
427427
submodules: recursive
428428
persist-credentials: false
429-
- uses: actions/setup-python@v5
429+
- uses: actions/setup-python@v6
430430
with:
431431
python-version: ${{ matrix.python-version }}
432432
- name: homebrew dependencies
@@ -543,7 +543,7 @@ jobs:
543543
echo PACKAGE_NAME=%PACKAGE_NAME%.zip >> %GITHUB_ENV%
544544
echo PACKAGE_PATH=build/%PACKAGE_NAME%.zip >> %GITHUB_ENV%
545545
echo UPLOAD_ASSET_TYPE=application/zip >> %GITHUB_ENV%
546-
- uses: actions/upload-artifact@v4
546+
- uses: actions/upload-artifact@v7
547547
if: env.PACKAGE_NAME != null
548548
with:
549549
name: ${{ env.PACKAGE_NAME }}

.github/workflows/coverity-scan.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
- uses: actions/checkout@v4
1111
with:
1212
submodules: recursive
13-
- uses: actions/setup-python@v5
13+
- uses: actions/setup-python@v6
1414
with:
1515
python-version: 3.9.x
1616

src/common/DisassemblyHelper.cpp

Lines changed: 129 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
#include "DisassemblyHelper.h"
22
#include "Cutter.h"
3+
#include "rz_types_base.h"
4+
5+
typedef struct mmio_lookup_context
6+
{
7+
QString selected;
8+
RVA mmio_address;
9+
} mmio_lookup_context_t;
10+
11+
static bool lookup_mmio_addr_cb(void *user, const ut64 key, const void *value)
12+
{
13+
mmio_lookup_context_t *ctx = (mmio_lookup_context_t *)user;
14+
if (ctx->selected == (const char *)value) {
15+
ctx->mmio_address = key;
16+
return false;
17+
}
18+
return true;
19+
}
320

421
DisassemblyTextBlockUserData::DisassemblyTextBlockUserData(const DisassemblyLine &line)
522
: line { line }
@@ -53,12 +70,59 @@ RVA DisassemblyHelper::readDisassemblyArrow(QTextCursor tc)
5370
return userData->line.arrow;
5471
}
5572

73+
DisassemblyHelper::BracketResult DisassemblyHelper::findBracketRange(const QString &line,
74+
int posInLine)
75+
{
76+
BracketResult res;
77+
int openBracket = line.lastIndexOf('[', posInLine);
78+
int closeBracket = line.indexOf(']', posInLine);
79+
80+
if (openBracket != -1 && closeBracket != -1) {
81+
bool isInside = true;
82+
for (int i = openBracket + 1; i < posInLine; ++i) {
83+
if (line[i] == ']') {
84+
isInside = false;
85+
break;
86+
}
87+
}
88+
if (isInside) {
89+
for (int i = posInLine; i < closeBracket; ++i) {
90+
if (line[i] == '[') {
91+
isInside = false;
92+
break;
93+
}
94+
}
95+
}
96+
97+
if (isInside) {
98+
res.found = true;
99+
res.start = openBracket;
100+
res.length = (closeBracket - openBracket) + 1;
101+
res.content = line.mid(res.start, res.length);
102+
}
103+
}
104+
return res;
105+
}
106+
56107
DisassemblyHelper::TargetContext DisassemblyHelper::getContextFromCursor(QTextCursor tc)
57108
{
109+
int originalPos = tc.position();
58110
tc.select(QTextCursor::WordUnderCursor);
111+
QString word = tc.selectedText();
112+
QString line = tc.block().text();
113+
int lineStart = tc.block().position();
114+
int posInLine = originalPos - lineStart;
115+
116+
auto bracketRes = findBracketRange(line, posInLine);
117+
if (bracketRes.found) {
118+
tc.setPosition(lineStart + bracketRes.start);
119+
tc.setPosition(lineStart + bracketRes.start + bracketRes.length, QTextCursor::KeepAnchor);
120+
word = bracketRes.content;
121+
}
122+
59123
TargetContext ctx;
60-
ctx.word = tc.selectedText();
61-
ctx.line = tc.block().text();
124+
ctx.word = word;
125+
ctx.line = line;
62126
ctx.offset = DisassemblyHelper::readDisassemblyOffset(tc);
63127
ctx.arrow = DisassemblyHelper::readDisassemblyArrow(tc);
64128
return ctx;
@@ -73,17 +137,35 @@ DisassemblyHelper::TargetAction DisassemblyHelper::resolveTarget(const TargetCon
73137
if (filter & TargetFilter::XRefComments) {
74138
bool showXRefComments = Core()->getConfigb("asm.xrefs");
75139
if (showXRefComments && isXRefFromComment(ctx.offset, ctx.line)) {
76-
res.offset = getXRefFromWord(ctx.offset, ctx.word);
140+
res.value = getXRefFromWord(ctx.offset, ctx.word);
77141
res.type = TargetType::XRefComment;
78142
return res;
79143
}
80144
}
81145

82-
if (filter & TargetFilter::Variables) {
146+
if (filter & TargetFilter::VariableValues) {
147+
QString inner = ctx.word;
148+
if (inner.startsWith('[') && inner.endsWith(']')) {
149+
inner = inner.mid(1, inner.length() - 2);
150+
}
151+
152+
if (ctx.offset != RVA_INVALID) {
153+
auto vars = Core()->getVariables(ctx.offset);
154+
for (auto &var : vars) {
155+
if (var.name == inner) {
156+
res.value = Core()->math(var.value);
157+
res.type = TargetType::VariableValue;
158+
return res;
159+
}
160+
}
161+
}
162+
}
163+
164+
if (filter & TargetFilter::VariableXrefs) {
83165
XrefDescription xref = Core()->getFirstXRefForVariable(ctx.word, ctx.offset);
84166
if (!xref.from_str.isEmpty() || !xref.to_str.isEmpty()) {
85-
res.offset = xref.from;
86-
res.type = TargetType::VariableName;
167+
res.value = xref.from;
168+
res.type = TargetType::VariableXRef;
87169
return res;
88170
}
89171
}
@@ -98,10 +180,50 @@ DisassemblyHelper::TargetAction DisassemblyHelper::resolveTarget(const TargetCon
98180
if (filter & TargetFilter::Arrows) {
99181
if (ctx.arrow != RVA_INVALID) {
100182
res.type = TargetType::Arrow;
101-
res.offset = ctx.arrow;
183+
res.value = ctx.arrow;
102184
return res;
103185
}
104186
}
105187

188+
if (!ctx.word.isEmpty()) {
189+
if (filter & TargetFilter::Registers) {
190+
const auto reg = Core()->getRegisterRefValue(ctx.word);
191+
if (!reg.name.isEmpty()) {
192+
res.type = TargetType::Register;
193+
res.value = Core()->math(reg.value);
194+
return res;
195+
}
196+
}
197+
198+
if (filter & TargetFilter::MMIO) {
199+
mmio_lookup_context_t mmio_ctx;
200+
mmio_ctx.selected = ctx.word;
201+
mmio_ctx.mmio_address = RVA_INVALID;
202+
auto core = Core()->lock();
203+
RzPlatformTarget *arch_target = core->analysis->arch_target;
204+
if (arch_target && arch_target->profile) {
205+
ht_up_foreach(arch_target->profile->registers_mmio, lookup_mmio_addr_cb, &mmio_ctx);
206+
}
207+
if (mmio_ctx.mmio_address != RVA_INVALID) {
208+
res.value = mmio_ctx.mmio_address;
209+
res.type = TargetType::MMIO;
210+
return res;
211+
}
212+
}
213+
214+
if (filter & TargetFilter::Memory) {
215+
QString stripped = ctx.word;
216+
if (stripped.startsWith('[') && stripped.endsWith(']')) {
217+
stripped = stripped.mid(1, stripped.length() - 2);
218+
if (Core()->isValidInputNumValue(stripped)
219+
|| Core()->isValidInputNumValue(ctx.word)) {
220+
res.value = Core()->math(ctx.word);
221+
res.type = TargetType::Memory;
222+
return res;
223+
}
224+
}
225+
}
226+
}
227+
106228
return res;
107229
}

src/common/DisassemblyHelper.h

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ namespace DisassemblyHelper {
2626
* @brief Identifies what kind of item was clicked or hovered
2727
*/
2828
enum class TargetType {
29-
VariableName,
29+
VariableXRef,
30+
VariableValue,
3031
TypeName,
3132
XRefComment,
3233
Arrow,
34+
Register,
35+
Memory,
36+
MMIO,
3337
None,
3438
};
3539

@@ -49,7 +53,7 @@ struct TargetContext
4953
*/
5054
struct TargetAction
5155
{
52-
RVA offset;
56+
RVA value;
5357
TargetType type;
5458
};
5559

@@ -58,15 +62,40 @@ struct TargetAction
5862
*/
5963
enum TargetFilter {
6064
XRefComments = 1 << 0,
61-
Variables = 1 << 1,
62-
Types = 1 << 2,
63-
Arrows = 1 << 3,
65+
VariableXrefs = 1 << 1,
66+
VariableValues = 1 << 2,
67+
Types = 1 << 3,
68+
Arrows = 1 << 4,
69+
Registers = 1 << 5,
70+
Memory = 1 << 6,
71+
MMIO = 1 << 7,
72+
73+
Standard = XRefComments | VariableXrefs | Types | Arrows,
74+
Debug = Registers | Memory | MMIO | VariableValues,
75+
All = Standard | Debug
76+
};
6477

65-
All = XRefComments | Variables | Types | Arrows
78+
/**
79+
* @brief Result of bracket detection
80+
*/
81+
struct BracketResult
82+
{
83+
bool found = false;
84+
int start = -1;
85+
int length = 0;
86+
QString content;
6687
};
6788

6889
DisassemblyTextBlockUserData *getUserData(const QTextBlock &block);
6990

91+
/**
92+
* @brief Finds the range and content of a bracketed expression under a given position
93+
* @param line The text line to search in
94+
* @param posInLine The cursor position within the line
95+
* @return BracketResult containing the found range and content
96+
*/
97+
BracketResult findBracketRange(const QString &line, int posInLine);
98+
7099
/**
71100
* @brief Finds the source (from) address of an XRef based on the text word under the cursor
72101
* @param offset The base offset of the line which contains an XREF to it

0 commit comments

Comments
 (0)