Skip to content

Commit

Permalink
feat(gdbdiff): run continuously + more useful output (#27)
Browse files Browse the repository at this point in the history
* feat(gdbdiff): print less and more readable output
* feat(gdbdiff): automatically fix register values for continuous running
  • Loading branch information
Turro75 authored May 16, 2021
1 parent b6ea0ec commit b783a0c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 44 deletions.
89 changes: 68 additions & 21 deletions debug/gdbdiff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,88 @@
* Copyright (C) 2021, Uri Shaked.
**/

import { GDBClient } from '../src/utils/gdbclient';
import { GDBClient, dumpUint32, registerNames } from '../src/utils/gdbclient';

function compareRegisters(emulator: Uint32Array, silicone: Uint32Array) {
function printComparedRegisters(
registers: Uint32Array,
emulator: Uint32Array,
silicone: Uint32Array
) {
for (let i = 0; i < registerNames.length; i++) {
let modified = ' ';
if (emulator[i] !== silicone[i]) {
modified = '*';
}
console.log(
registerNames[i] + modified,
'\t\t0x' +
dumpUint32(registers[i]) +
'\t0x' +
dumpUint32(emulator[i]) +
'\t0x' +
dumpUint32(silicone[i])
);
if (registerNames[i] === 'xPSR' && modified === '*') {
console.log(
'Flags\t\t',
printFlags(registers[i]),
'\t',
printFlags(emulator[i]),
'\t',
printFlags(silicone[i])
);
}
}
}

function printFlags(xpsr: number) {
let negative = xpsr & 0x80000000 ? 'N' : '-';
let zero = xpsr & 0x40000000 ? 'Z' : '-';
let carry = xpsr & 0x20000000 ? 'C' : '-';
let overflow = xpsr & 0x10000000 ? 'O' : '-';
return `[${negative}${zero}${carry}${overflow}]`;
}

async function compareFixRegisters(
emulator: Uint32Array,
silicone: Uint32Array,
toFixClient: GDBClient
) {
let result = true;
for (let i = 0; i < emulator.length; i++) {
if (emulator[i] !== silicone[i]) {
console.log(`Mismatch register ${i}: emulator ${emulator[i]} != silicone ${silicone[i]}`);
await toFixClient.writeRegister(i, silicone[i]);
result = false;
}
}
return result;
}

async function main() {
const client1 = new GDBClient();
const client2 = new GDBClient();
await client1.connect('localhost');
await client2.connect('raspberrypi');
const emulatorClient = new GDBClient();
const siliconeClient = new GDBClient();
await emulatorClient.connect('localhost', 3334);
await siliconeClient.connect('localhost', 3333);
// Disable interrupts
await client1.writeRegister(19, 1, 8);
await client2.writeRegister(19, 1, 8);
await emulatorClient.writeRegister(19, 1, 8);
await siliconeClient.writeRegister(19, 1, 8);
// Start diffing
for (let counter = 0; ; counter++) {
const regSet1 = await client1.readRegisters();
const regSet2 = await client2.readRegisters();
console.log(`Instruction ${counter}`);
await client1.dumpRegisters();
if (!compareRegisters(regSet1, regSet2)) {
console.log('PC (emulator): ', regSet1[15].toString(16));
console.log('PC (silicone): ', regSet2[15].toString(16));
break;
let prevRegSet = await siliconeClient.readRegisters();
for (let counter = 1; ; counter++) {
const emulatorRegSet = await emulatorClient.readRegisters();
const siliconeRegSet = await siliconeClient.readRegisters();

if (!(await compareFixRegisters(emulatorRegSet, siliconeRegSet, emulatorClient))) {
console.log('\n\nMismatch after ', counter, ' compared instructions');
console.log('\nRegister\tStartValue\tEmulator\tSilicone');
printComparedRegisters(prevRegSet, emulatorRegSet, siliconeRegSet);
}
prevRegSet = emulatorRegSet;
await emulatorClient.singleStep();
await siliconeClient.singleStep();
if (counter % 200 === 0) {
console.log(`Successfully compared ${counter} instructions`);
}
await client1.singleStep();
await client2.singleStep();
console.log('---');
}
}

Expand Down
48 changes: 25 additions & 23 deletions src/utils/gdbclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,27 @@ import {
gdbMessage,
} from './gdb';

function dumpUint32(value: number) {
export const registerNames = [
'r0',
'r1',
'r2',
'r3',
'r4',
'r5',
'r6',
'r7',
'r8',
'r9',
'r10',
'r11',
'r12',
'sp',
'lr',
'pc',
'xPSR',
];

export function dumpUint32(value: number) {
let valueStr = value.toString(16);
while (valueStr.length < 8) {
valueStr = '0' + valueStr;
Expand Down Expand Up @@ -84,7 +104,7 @@ export class GDBClient {
}
let response = await this.sendCommand(`qRcmd,${encodeHexBuf(buf)}`);
while (response !== 'OK' && response[0] === 'O') {
this.socket.write('+');
this.socket.write('+');
response = await this.readResponse(false);
}
if (response !== 'OK') {
Expand All @@ -98,25 +118,6 @@ export class GDBClient {
}

async dumpRegisters() {
const registerNames = [
'r0',
'r1',
'r2',
'r3',
'r4',
'r5',
'r6',
'r7',
'r8',
'r9',
'r10',
'r11',
'r12',
'sp',
'lr',
'pc',
'xPSR',
];
const registers = await this.readRegisters();
for (let i = 0; i < registerNames.length; i++) {
console.log(registerNames[i], '=', '0x' + dumpUint32(registers[i]));
Expand All @@ -132,8 +133,9 @@ export class GDBClient {
}

async writeRegister(index: number, value: number, width: 8 | 32 = 32) {
const response = await this.sendCommand(`P${encodeHexByte(index)}=${
width === 32 ? encodeHexUint32(value) : encodeHexByte(value)}`);
const response = await this.sendCommand(
`P${encodeHexByte(index)}=${width === 32 ? encodeHexUint32(value) : encodeHexByte(value)}`
);
if (response !== 'OK') {
throw new Error(`Invalid writeRegister response: ${response}`);
}
Expand Down

0 comments on commit b783a0c

Please sign in to comment.