Skip to content

Commit c9bedc0

Browse files
authored
Fix remove mappings (#93)
1 parent 7a3cd2d commit c9bedc0

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

src/OID.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,20 @@ static ExitStatus::ExitStatus runScript(const std::string &fileName,
323323
*/
324324
if (oidConfig.attachToProcess) {
325325
if (oidConfig.removeMappings) {
326+
ExitStatus::ExitStatus ret = ExitStatus::Success;
327+
326328
if (!oid->segConfigExists()) {
327329
LOG(INFO) << "No config exists for pid " << oidConfig.pid
328330
<< " : cannot remove mappings";
331+
ret = ExitStatus::UsageError;
329332
} else if (!oid->unmapSegments(true)) {
330333
LOG(ERROR) << "Failed to remove segments in target process with PID "
331334
<< oidConfig.pid;
332-
return ExitStatus::SegmentRemovalError;
335+
ret = ExitStatus::SegmentRemovalError;
333336
}
334337

335-
return ExitStatus::Success;
338+
oid->contTargetThread();
339+
return ret;
336340
}
337341

338342
if (oidConfig.dataSegSize > 0) {
@@ -679,6 +683,14 @@ int main(int argc, char *argv[]) {
679683
return ExitStatus::UsageError;
680684
}
681685

686+
/*
687+
* This is unfortunately necessary to stop users having to specify a script
688+
* just to remove mappings (which doesn't make sense).
689+
*/
690+
if (oidConfig.removeMappings && scriptFile.empty() && scriptSource.empty()) {
691+
scriptSource = "entry:unknown_function:arg0";
692+
}
693+
682694
OICodeGen::Config codeGenConfig{
683695
.useDataSegment = true,
684696
.chaseRawPointers = chaseRawPointers,

test/integration.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import glob
22
import json
3+
import os
34
import os.path
45
import shutil
56
import subprocess
67
import tempfile
8+
import time
79
import unittest
810
from contextlib import contextmanager
911
from enum import Enum
@@ -237,6 +239,63 @@ def test_no_args_shows_help(self):
237239
self.expectReturncode(proc, ExitStatus.USAGE_ERROR)
238240
self.assertIn(b"usage: ", proc.stdout)
239241

242+
def test_remove_mappings(self):
243+
with subprocess.Popen(
244+
f"{self.binary_path} 100",
245+
stdout=subprocess.PIPE,
246+
stderr=subprocess.PIPE,
247+
text=True,
248+
shell=True,
249+
) as target_proc:
250+
pid = target_proc.pid
251+
252+
# The sleep is unfortunate but it allows the segments to get
253+
# established in the target process.
254+
time.sleep(2)
255+
256+
numsegs = subprocess.run(
257+
f"cat /proc/{pid}/maps | wc -l",
258+
shell=True,
259+
capture_output=True,
260+
check=True,
261+
)
262+
beforeSegs = int(numsegs.stdout.decode("ascii"))
263+
264+
proc = subprocess.run(
265+
f"{self.oid} --script {self.script()} -t 1 --pid {pid}",
266+
shell=True,
267+
stdout=subprocess.PIPE,
268+
stderr=subprocess.PIPE,
269+
)
270+
self.expectReturncode(proc, ExitStatus.SUCCESS)
271+
272+
numsegs = subprocess.run(
273+
f"cat /proc/{pid}/maps | wc -l",
274+
shell=True,
275+
capture_output=True,
276+
check=True,
277+
)
278+
afterSegs = int(numsegs.stdout.decode("ascii"))
279+
self.assertEqual(beforeSegs, afterSegs - 2)
280+
281+
# remove both the text and data segments
282+
proc = subprocess.run(
283+
f"{self.oid} -r --pid {pid}",
284+
shell=True,
285+
stdout=subprocess.PIPE,
286+
stderr=subprocess.PIPE,
287+
)
288+
self.expectReturncode(proc, ExitStatus.SUCCESS)
289+
290+
numsegs = subprocess.run(
291+
f"cat /proc/{pid}/maps | wc -l",
292+
shell=True,
293+
capture_output=True,
294+
check=True,
295+
)
296+
afterRemSegs = int(numsegs.stdout.decode("ascii"))
297+
self.assertEqual(beforeSegs, afterRemSegs)
298+
240299
def test_metrics_data_is_generated(self):
241300
with self.spawn_oid(self.script()) as proc:
242301
self.expectReturncode(proc, ExitStatus.SUCCESS)

0 commit comments

Comments
 (0)