Skip to content

Commit

Permalink
Fixing issues noticed during testing. (#69)
Browse files Browse the repository at this point in the history
- Added json file creation to GDB script, so user does not need to create or modify Uncore json file, just needs to enter any command settings (like sysroot or solib-search-path setting) before running 'setup_session' command.
- Added Crash server/Uncore and GDB synchronization needed when Uncore takes longer time to be executed.
+ some smaller changes
  • Loading branch information
ppetrovic98 authored Mar 6, 2024
1 parent bfcc3ce commit a5291c9
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 4 deletions.
36 changes: 34 additions & 2 deletions llvm-15.0.3/lldb/tools/lldb-crash-server/UncoreHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#include <iostream>
#include <memory>
#include <regex>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>

#include "UncoreHandler.h"

Expand All @@ -14,14 +17,36 @@ bool lldb::UncoreHandler::RunUncore() {

int status = std::system(cmd.c_str());

if (status != 0) {
std::string loader_file_path = m_working_dir + "/outdir/loader.bin";

if (status != 0 && !llvm::sys::fs::exists(loader_file_path)) {
llvm::errs() << "Uncore execution failed.\n";
return false;
}

return true;
}

bool WriteToPipe(std::string working_dir) {
std::string pipe_path = working_dir + "/gdb_lldb_signal_pipe";
int fd = open(pipe_path.c_str(), O_WRONLY);
if (fd == -1) {
llvm::errs() << "Failed to open the FIFO pipe. \n";
return false;
}

std::string message = "Crash server is ready.";
if (write(fd, message.c_str(), message.size()) == -1) {
llvm::errs() << "Failed to write into the pipe. \n";
close(fd);
return false;
}

close(fd);
return true;
}


::pid_t lldb::UncoreHandler::RunLoaderProcess() {

::pid_t pid = fork();
Expand All @@ -40,7 +65,14 @@ ::pid_t lldb::UncoreHandler::RunLoaderProcess() {

llvm::errs() << "Failed to execute loader.bin process. \n";
} else {
sleep(2);
// TODO: Some kind of synchronization should be implemented with loader.bin
// so this can be removed
sleep(20);

if (!WriteToPipe(m_working_dir)) {
return LLDB_INVALID_PROCESS_ID;
}

return pid;
}

Expand Down
2 changes: 1 addition & 1 deletion llvm-15.0.3/lldb/tools/lldb-crash-server/UncoreHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class UncoreHandler {
<< "\n";
exit(1);
}
m_working_dir = cwd.str().data();
m_working_dir = cwd.c_str();
}

bool RunUncore();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import subprocess
import socket
import os
import json
from contextlib import closing
from pty import STDERR_FILENO, STDOUT_FILENO

Expand All @@ -19,6 +20,9 @@
core_registers = {}
live_registers = {}

# Current working directory
cwd = os.getcwd()

# Global variable to store Crash server path
lldb_crash_server_path = None

Expand All @@ -41,12 +45,14 @@ def __init__(self):
)

def invoke(self, arg, from_tty):
global lldb_crash_server_path
global lldb_crash_server_path, cwd

args = arg.split()
if len(args) != 2:
print("Usage: setup_session <binary> <corefile>")
return

gdb_settings = self.get_gdb_setting()

binary, corefile = args
gdb.execute(f"file {binary}")
Expand All @@ -64,12 +70,22 @@ def invoke(self, arg, from_tty):
if lldb_crash_server_path is None:
print("Crash server path is not set.")
return

# Create uncore json file
self.create_json_file(corefile, binary, gdb_settings)

# Create a named pipe
pipe_path = os.path.join(cwd, "gdb_lldb_signal_pipe")
self.create_pipe(pipe_path)

# Start Crash server as a subprocess
port = self.find_free_port()
subprocess.Popen([lldb_crash_server_path, "g", f"localhost:{port}", binary,
"--uncore-json", "./uncore.json"], stdout=STDOUT_FILENO, stderr=STDERR_FILENO)

# Read from a named pipe (waiting for a signal from Crash server)
self.read_from_pipe(pipe_path)

# Connect to remote target
gdb.execute(f"target remote localhost:{port}")

Expand Down Expand Up @@ -98,6 +114,92 @@ def find_free_port(self):
s.bind(('localhost', 0))
return s.getsockname()[1]

def create_json_file(self, core_path, binary_path, gdb_settings):
global cwd

# Set the uncore output and json file path
output_path = os.path.join(cwd, "outdir")
json_path = os.path.join(cwd, "uncore.json")

data = {
"core": core_path,
"binos_root": "",
"entry_point": "main",
"prog": binary_path,
"pid": "",
"additional_resources": "",
"custom_o_file": [],
"output_directory": output_path,
"hot_patch": {
},
"gdbparse": {
"gdb": "gdb",
"args": [
binary_path,
core_path
],
"kwargs": {
}
}
}

if len(gdb_settings) > 1:
# Create a gdb script with all commands from gdb_settings
script_path = os.path.join(cwd, "gdb_uncore.script")
with open(script_path, "w") as script_file:
for cmd in gdb_settings:
script_file.write(cmd + "\n")
data["gdbparse"]["kwargs"]["-x"] = script_path
elif len(gdb_settings) == 1:
data["gdbparse"]["kwargs"]["-ex"] = gdb_settings[0]

# Convert the JSON data to a string
json_str = json.dumps(data, indent=4)

# Write the JSON string to a file in the current working directory
try:
with open(json_path, "w") as json_file:
json_file.write(json_str)
print(f"JSON file successfully created at: {json_path}")
except Exception as e:
print(f"Error: {e}")

# Get gdb session settings
def get_gdb_setting(self):
gdb_settings = []

# Retrieve the process sysroot setting
sysroot_setting = gdb.execute("show sysroot", to_string=True)
if sysroot_setting.startswith("The current system root is"):
sysroot_path = sysroot_setting.split('"')[1].strip()
if sysroot_path != "target:" and sysroot_path != "":
gdb_settings.append(f"set sysroot {sysroot_path}")

# Retrieve and process solib-search-path setting
solib_search_path_setting = gdb.execute("show solib-search-path", to_string=True)
if solib_search_path_setting.startswith("The search path for loading non-absolute shared library symbol files is"):
solib_search_path = solib_search_path_setting.split(' is ')[1].strip()
if solib_search_path != "." and solib_search_path != "":
gdb_settings.append(f"set solib-search-path {solib_search_path}")

return gdb_settings

# Create a named FIFO pipe
def create_pipe(self, pipe_path):
try:
os.mkfifo(pipe_path)
except OSError as e:
print(f"Error creating the pipe: {e}")

# Read from the named pipe
def read_from_pipe(self, pipe_path):
try:
with open(pipe_path, "r") as pipe:
message = pipe.read()
print(message)
except Exception as e:
print(f"Error reading from the pipe: {e}")


class RestoreRegisters(gdb.Command):
"""Restore registers to saved values from either corefile or live process."""
Expand Down

0 comments on commit a5291c9

Please sign in to comment.