Last active
September 13, 2018 16:53
-
-
Save goldshtn/56d3daae842ccad44612cdacd68bac29 to your computer and use it in GitHub Desktop.
Revisions
-
goldshtn renamed this gist
Feb 8, 2018 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
goldshtn revised this gist
Feb 8, 2018 . 1 changed file with 12 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,14 @@ #!/usr/bin/env python # # USAGE: place-probe [-h] [--dry-run] [--debug] PID METHOD # # This tool helps place dynamic probes on .NET methods that were # CrossGen-generated (compiled ahead of time). To use the tool, # the CrossGen-generated assemblies need to have perfmaps generated # by CrossGen /CreatePerfMap, expected in the /tmp directory. # # Copyright (C) 2018, Sasha Goldshtein # Licensed under the MIT License import argparse import os @@ -41,7 +51,8 @@ def place_probe(path, offset): subprocess.check_call(command, shell=True) parser = argparse.ArgumentParser(description="Place dynamic tracing probes on a managed method " + "that resides in a crossgen-compiled assembly. For .NET Core on Linux.", epilog="EXAMPLE: ./place-probe.py 1234 'Thread::Sleep'") parser.add_argument("pid", type=int, help="the dotnet process id") parser.add_argument("symbol", type=str, help="the symbol on which to place the probe") parser.add_argument("--dry-run", action="store_true", -
goldshtn revised this gist
Feb 8, 2018 . 1 changed file with 20 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,20 @@ create: sudo docker run -v $(CURDIR):/app -it --rm microsoft/dotnet:sdk dotnet new console -o /app build: sudo docker run -it --rm -v $(CURDIR):/app microsoft/dotnet:sdk bash -c \ "cd /app && dotnet publish -c Release -o /app/out -r linux-x64" out/crossgen /Platform_Assemblies_Paths out out/app.dll mv out/app.ni.exe out/app.dll run: COMPlus_PerfMapEnabled=1 $(CURDIR)/out/app generate: ./dotnet-mapgen-v3.py generate `pidof app` record: sudo perf record -e probe_System:* -p `pidof app` -g -- sleep 10 sudo perf probe --del=* sudo chown ubuntu perf.data perf script -
goldshtn created this gist
Feb 8, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,76 @@ #!/usr/bin/env python import argparse import os import re import subprocess class Section(object): def __init__(self, start, perms, offset, path): self.start = int(start, 16) self.perms = perms self.offset = int(offset, 16) self.path = path def assembly_from_map_file(map_file): return re.match("/tmp/(.*)\.ni\.{.*}.map", map_file).group(1) + ".dll" def all_sections(pid): sections = {} with open("/proc/%d/maps" % pid, "r") as maps: for line in maps: match = re.match(r"(\S+)-\S+\s+(\S+)\s+(\S+)\s+\S+\s+\S+\s+(\S+)", line.strip()) if match is None: continue start, perms, offset, path = match.group(1, 2, 3, 4) if '/' not in path: continue filename = os.path.basename(path) section = Section(start, perms, offset, path) if filename in sections: sections[filename].append(section) else: sections[filename] = [section] return sections def place_probe(path, offset): command = "sudo perf probe -x %s --add 0x%x" % (path, offset) if args.dry_run: print(command) else: subprocess.check_call(command, shell=True) parser = argparse.ArgumentParser(description="Place dynamic tracing probes on a managed method " + "that resides in a crossgen-compiled assembly. For .NET Core on Linux.") parser.add_argument("pid", type=int, help="the dotnet process id") parser.add_argument("symbol", type=str, help="the symbol on which to place the probe") parser.add_argument("--dry-run", action="store_true", help="print the symbol and the command but don't place the probe") parser.add_argument("--debug", action="store_true", help="print diagnostic information") args = parser.parse_args() sections = all_sections(args.pid) output = subprocess.check_output("grep '%s' /tmp/*.ni.*.map" % args.symbol, shell=True) for line in output.strip().split('\n'): parts = line.split() map_file, address = parts[0].split(':') address = int(address, 16) assembly = assembly_from_map_file(map_file) symbol = str.join(' ', parts[2:]) if args.dry_run: print("\n" + symbol) first_section = sections[assembly][0] exec_section = [section for section in sections[assembly] if 'r-xp' == section.perms][0] offset_from_first = exec_section.start - first_section.start offset_in_file = exec_section.offset final_address = address - offset_from_first + offset_in_file if args.debug: print("address: %x, offset_from_first: %x, offset_in_file: %x, final_address: %x" % (address, offset_from_first, offset_in_file, final_address)) place_probe(exec_section.path, final_address)