From 144503d543f1a43d5353d750da5ae253c083c5e9 Mon Sep 17 00:00:00 2001 From: Kale Blankenship Date: Mon, 26 Nov 2018 21:00:24 -0800 Subject: go: replace PC jumps with labels Rewrite PC jumps with labels so that it's clear where the jumps are to. --- lib/compilers/golang.js | 113 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 16 deletions(-) (limited to 'lib/compilers/golang.js') diff --git a/lib/compilers/golang.js b/lib/compilers/golang.js index bbf666576..f558c5eb3 100644 --- a/lib/compilers/golang.js +++ b/lib/compilers/golang.js @@ -26,38 +26,119 @@ const BaseCompiler = require('../base-compiler'), _ = require('underscore'), utils = require('../utils'); +// Each arch has a list of jump instructions in +// Go source src/cmd/asm/internal/arch. +const jumpPrefixes = [ + 'j', + 'b', + + // arm + 'cb', + 'tb', + + // s390x + 'cmpb', + 'cmpub' +]; + class GolangCompiler extends BaseCompiler { convertNewGoL(code) { - const re = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(([^:]+):([0-9]+)\)\s*([A-Z]+)(.*)/; - const reUnknown = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(\)\s*([A-Z]+)(.*)/; + const re = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?([0-9]+)\s*\(([^:]+):([0-9]+)\)\s*([A-Z]+)(.*)/; + const reUnknown = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?([0-9]+)\s*\(\)\s*([A-Z]+)(.*)/; + const reFunc = /TEXT\s+[".]*(\S+)\(SB\)/; let prevLine = null; let file = null; let fileCount = 0; - return _.compact(code.map(obj => { + let func = null; + let labels = {}; + let usedLabels = {}; + let lines = code.map(obj => { + let pcMatch = null; + let fileMatch = null; + let lineMatch = null; + let ins = null; + let args = null; + const line = obj.text; let match = line.match(re); if (match) { - let res = ""; - if (file !== match[2]) { - fileCount++; - res += "\t.file " + fileCount + ' "' + match[2] + '"\n'; - file = match[2]; - } - if (prevLine !== match[3]) { - res += "\t.loc " + fileCount + " " + match[3] + " 0\n"; - prevLine = match[3]; - } - return res + "\t" + match[4].toLowerCase() + match[5]; + pcMatch = match[2]; + fileMatch = match[3]; + lineMatch = match[4]; + ins = match[5]; + args = match[6]; } else { match = line.match(reUnknown); if (match) { - return "\t" + match[2].toLowerCase() + match[3]; + pcMatch = match[2]; + ins = match[3]; + args = match[4]; } else { return null; } } - })).join("\n"); + match = line.match(reFunc); + if (match) { + // Normalize function name. + func = match[1].replace(/[.()*]+/g, "_"); + } + + let res = []; + if (pcMatch && !labels[pcMatch]) { + // Create pseudo-label. + let label = pcMatch.replace(/^0{0,4}/, ''); + label = `${func}_pc${label}:`; + if (!labels[label]) { + res.push(label); + labels[label] = true; + } + } + + if (fileMatch && file !== fileMatch) { + fileCount++; + res.push(`\t.file ${fileCount} "${fileMatch}"`); + file = fileMatch; + } + + if (lineMatch && prevLine !== lineMatch) { + res.push(`\t.loc ${fileCount} ${lineMatch} 0`); + prevLine = lineMatch; + } + + ins = ins.toLowerCase(); + args = this.replaceJump(func, ins, args, usedLabels); + res.push(`\t${ins}${args}`); + return res; + }); + + // Find unused pseudo-labels so they can be filtered out. + let unusedLabels = _.mapObject(labels, (val, key) => { return !usedLabels[key]; }); + + return _.chain(lines) + .flatten() + .compact() + .filter((line) => { return !unusedLabels[line]; }) + .value() + .join("\n"); + } + + replaceJump(func, ins, args, usedLabels) { + // Check if last argument is a decimal number. + const re = /(\s+)([0-9]+)(\s?)$/; + let match = args.match(re); + if (!match) { + return args; + } + + // Check instruction has a jump prefix + if (_.any(jumpPrefixes, (prefix) => { return ins.startsWith(prefix); })) { + let label = `${func}_pc${match[2]}`; + usedLabels[label + ":"] = true; // record label use for later filtering + return `${match[1]}${label}${match[3]}`; + } + + return args; } extractLogging(stdout) { -- cgit v1.2.3 From d6d605595ea465764e5cfff66cbde51dffb77b8f Mon Sep 17 00:00:00 2001 From: Kale Blankenship Date: Wed, 28 Nov 2018 18:19:31 -0800 Subject: Add tests for Go labels and handle function name collisions. --- lib/compilers/golang.js | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'lib/compilers/golang.js') diff --git a/lib/compilers/golang.js b/lib/compilers/golang.js index f558c5eb3..7e6af5362 100644 --- a/lib/compilers/golang.js +++ b/lib/compilers/golang.js @@ -50,6 +50,7 @@ class GolangCompiler extends BaseCompiler { let file = null; let fileCount = 0; let func = null; + let funcCollisions = {}; let labels = {}; let usedLabels = {}; let lines = code.map(obj => { @@ -82,13 +83,30 @@ class GolangCompiler extends BaseCompiler { if (match) { // Normalize function name. func = match[1].replace(/[.()*]+/g, "_"); + + // It's possible for normalized function names to collide. + // Keep a count of collisions per function name. Labels get + // suffixed with _[collisions] when collisions > 0. + let collisions = funcCollisions[func]; + if (collisions == null) { + collisions = 0; + } else { + collisions++; + } + + funcCollisions[func] = collisions; } let res = []; if (pcMatch && !labels[pcMatch]) { // Create pseudo-label. let label = pcMatch.replace(/^0{0,4}/, ''); - label = `${func}_pc${label}:`; + let suffix = ''; + if (funcCollisions[func] > 0) { + suffix = `_${funcCollisions[func]}`; + } + + label = `${func}_pc${label}${suffix}:`; if (!labels[label]) { res.push(label); labels[label] = true; @@ -107,7 +125,7 @@ class GolangCompiler extends BaseCompiler { } ins = ins.toLowerCase(); - args = this.replaceJump(func, ins, args, usedLabels); + args = this.replaceJump(func, funcCollisions[func], ins, args, usedLabels); res.push(`\t${ins}${args}`); return res; }); @@ -123,7 +141,7 @@ class GolangCompiler extends BaseCompiler { .join("\n"); } - replaceJump(func, ins, args, usedLabels) { + replaceJump(func, collisions, ins, args, usedLabels) { // Check if last argument is a decimal number. const re = /(\s+)([0-9]+)(\s?)$/; let match = args.match(re); @@ -134,6 +152,9 @@ class GolangCompiler extends BaseCompiler { // Check instruction has a jump prefix if (_.any(jumpPrefixes, (prefix) => { return ins.startsWith(prefix); })) { let label = `${func}_pc${match[2]}`; + if (collisions > 0) { + label += `_${collisions}`; + } usedLabels[label + ":"] = true; // record label use for later filtering return `${match[1]}${label}${match[3]}`; } -- cgit v1.2.3 From e892d3506fe977d838ad3a52c2db28c05191950d Mon Sep 17 00:00:00 2001 From: Partouf Date: Tue, 8 Jan 2019 03:20:30 +0100 Subject: change argument parser for some compilers --- lib/compilers/golang.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/compilers/golang.js') diff --git a/lib/compilers/golang.js b/lib/compilers/golang.js index 7e6af5362..8c298ad38 100644 --- a/lib/compilers/golang.js +++ b/lib/compilers/golang.js @@ -23,6 +23,7 @@ // POSSIBILITY OF SUCH DAMAGE. const BaseCompiler = require('../base-compiler'), + argumentParsers = require("./argument-parsers"), _ = require('underscore'), utils = require('../utils'); @@ -192,6 +193,10 @@ class GolangCompiler extends BaseCompiler { } return execOptions; } + + getArgumentParser() { + return argumentParsers.Clang; + } } module.exports = GolangCompiler; -- cgit v1.2.3