Skip to content

Instantly share code, notes, and snippets.

@FrankSpierings
Created July 26, 2024 15:29
Show Gist options
  • Save FrankSpierings/568fd431050a4de709b81132eb1c020a to your computer and use it in GitHub Desktop.
Save FrankSpierings/568fd431050a4de709b81132eb1c020a to your computer and use it in GitHub Desktop.
Simple gcc demangler (thanks Claude)
function demangle(mangledName, options = {}) {
const { nameOnly = false } = options;
let index = 0;
function parseNumber() {
let num = '';
while (index < mangledName.length && /\d/.test(mangledName[index])) {
num += mangledName[index++];
}
return parseInt(num, 10);
}
function parseIdentifier() {
const length = parseNumber();
const identifier = mangledName.substr(index, length);
index += length;
return identifier;
}
function parseType() {
if (index >= mangledName.length) return '';
switch (mangledName[index]) {
case 'v': index++; return 'void';
case 'b': index++; return 'bool';
case 'c': index++; return 'char';
case 'a': index++; return 'signed char';
case 'h': index++; return 'unsigned char';
case 's': index++; return 'short';
case 't': index++; return 'unsigned short';
case 'i': index++; return 'int';
case 'j': index++; return 'unsigned int';
case 'l': index++; return 'long';
case 'm': index++; return 'unsigned long';
case 'x': index++; return 'long long';
case 'y': index++; return 'unsigned long long';
case 'f': index++; return 'float';
case 'd': index++; return 'double';
case 'e': index++; return 'long double';
case 'P': index++; return parseType() + '*';
case 'N': {
index++;
let result = '';
while (mangledName[index] !== 'E') {
result += parseIdentifier() + '::';
}
index++; // Skip 'E'
return result.slice(0, -2); // Remove last '::'
}
default:
if (/\d/.test(mangledName[index])) {
return parseIdentifier();
}
index++;
return 'unknown';
}
}
function parseName() {
let result = '';
if (mangledName[index] === 'N') {
index++; // Skip 'N'
while (mangledName[index] !== 'E') {
result += parseIdentifier() + '::';
}
index++; // Skip 'E'
return result.slice(0, -2); // Remove last '::'
} else {
return parseIdentifier();
}
}
if (mangledName.startsWith('_Z')) {
index = 2;
let result = parseName();
if (!nameOnly) {
result += '(';
// Parse parameters
let params = [];
while (index < mangledName.length) {
let param = parseType();
if (param) params.push(param);
}
result += params.join(', ');
result += ')';
}
return result;
} else {
return mangledName; // Not a mangled name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment