diff --git a/src/profile-logic/symbol-store.ts b/src/profile-logic/symbol-store.ts index df39c76a30..39b77f5561 100644 --- a/src/profile-logic/symbol-store.ts +++ b/src/profile-logic/symbol-store.ts @@ -245,6 +245,24 @@ export class SymbolStore { ); return false; } + // Skip pseudo-modules such as [vdso], [vsyscall], [heap], [stack] and + // [anon:...]. These are kernel- or allocator-provided mappings with no + // symbol files, so requesting them is always pointless. Worse, the + // Mozilla symbolication server rejects the entire batched request with an + // HTTP 400 ("invalid debug_filename") when any job's module name contains + // brackets, which would prevent every other library in the same chunk + // (e.g. libxul) from being symbolicated. + if (debugName.startsWith('[')) { + errorCb( + request, + new SymbolsNotFoundError( + `Cannot symbolicate pseudo-library ${debugName}`, + request.lib, + new Error('Pseudo-library without symbols') + ) + ); + return false; + } return true; }); diff --git a/src/test/unit/symbol-store.test.ts b/src/test/unit/symbol-store.test.ts index 4b88f7aa7d..3a1c6842ff 100644 --- a/src/test/unit/symbol-store.test.ts +++ b/src/test/unit/symbol-store.test.ts @@ -270,6 +270,10 @@ describe('SymbolStore', function () { debugName: '', breakpadId: 'empty-debugname', }, + { + debugName: '[vdso]', + breakpadId: 'dont-care', + }, ]; const symbolTable = new Map([ @@ -291,6 +295,9 @@ describe('SymbolStore', function () { const { debugName, breakpadId } = request.lib; expect(debugName).not.toEqual(''); expect(breakpadId).not.toEqual(''); + // Pseudo-libraries must be filtered out before reaching the server, + // otherwise they cause the whole batched request to be rejected. + expect(debugName.startsWith('[')).toBe(false); await fakeSymbolStore.getSymbols( [request], (lib, results) => { @@ -367,7 +374,7 @@ describe('SymbolStore', function () { // Empty debugNames or breakpadIds should cause errors. And if symbols are // not available from any source, all errors along the way should be included // in the reported error. - expect([...failedLibs]).toBeArrayOfSize(3); + expect([...failedLibs]).toBeArrayOfSize(4); expect(failedLibs.get('empty-breakpadid')).toEqual( expect.objectContaining({ message: expect.stringContaining('Invalid debugName or breakpadId'), @@ -379,6 +386,14 @@ describe('SymbolStore', function () { }) ); + // Pseudo-libraries such as [vdso] should fail without being sent to any + // symbol source, so they can't take down the rest of the batch. + expect(failedLibs.get('[vdso]')).toEqual( + expect.objectContaining({ + message: expect.stringContaining('Cannot symbolicate pseudo-library'), + }) + ); + // For error objects, Jest's deep equality checks only check the message. expect(failedLibs.get('available-from-neither')).toEqual( new SymbolsNotFoundError(