Permalink
Cannot retrieve contributors at this time
228 lines (228 sloc)
10 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/lib/tracer-config.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | |
if (k2 === undefined) k2 = k; | |
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | |
}) : (function(o, m, k, k2) { | |
if (k2 === undefined) k2 = k; | |
o[k2] = m[k]; | |
})); | |
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | |
Object.defineProperty(o, "default", { enumerable: true, value: v }); | |
}) : function(o, v) { | |
o["default"] = v; | |
}); | |
var __importStar = (this && this.__importStar) || function (mod) { | |
if (mod && mod.__esModule) return mod; | |
var result = {}; | |
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | |
__setModuleDefault(result, mod); | |
return result; | |
}; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
exports.getCombinedTracerConfig = exports.concatTracerConfigs = exports.getTracerConfigForLanguage = exports.getTracerConfigForCluster = exports.endTracingForCluster = void 0; | |
const fs = __importStar(require("fs")); | |
const path = __importStar(require("path")); | |
const codeql_1 = require("./codeql"); | |
const languages_1 = require("./languages"); | |
const util = __importStar(require("./util")); | |
const util_1 = require("./util"); | |
const CRITICAL_TRACER_VARS = new Set([ | |
"SEMMLE_PRELOAD_libtrace", | |
"SEMMLE_RUNNER", | |
"SEMMLE_COPY_EXECUTABLES_ROOT", | |
"SEMMLE_DEPTRACE_SOCKET", | |
"SEMMLE_JAVA_TOOL_OPTIONS", | |
]); | |
async function endTracingForCluster(config) { | |
// If there are no traced languages, we don't need to do anything. | |
if (!config.languages.some(languages_1.isTracedLanguage)) | |
return; | |
const envVariablesFile = path.resolve(config.dbLocation, "temp/tracingEnvironment/end-tracing.json"); | |
if (!fs.existsSync(envVariablesFile)) { | |
throw new Error(`Environment file for ending tracing not found: ${envVariablesFile}`); | |
} | |
try { | |
const endTracingEnvVariables = JSON.parse(fs.readFileSync(envVariablesFile, "utf8")); | |
for (const [key, value] of Object.entries(endTracingEnvVariables)) { | |
if (value !== null) { | |
process.env[key] = value; | |
} | |
else { | |
delete process.env[key]; | |
} | |
} | |
} | |
catch (e) { | |
throw new Error(`Failed to parse file containing end tracing environment variables: ${e}`); | |
} | |
} | |
exports.endTracingForCluster = endTracingForCluster; | |
async function getTracerConfigForCluster(config) { | |
const tracingEnvVariables = JSON.parse(fs.readFileSync(path.resolve(config.dbLocation, "temp/tracingEnvironment/start-tracing.json"), "utf8")); | |
return { | |
spec: tracingEnvVariables["ODASA_TRACER_CONFIGURATION"], | |
env: tracingEnvVariables, | |
}; | |
} | |
exports.getTracerConfigForCluster = getTracerConfigForCluster; | |
async function getTracerConfigForLanguage(codeql, config, language) { | |
const env = await codeql.getTracerEnv(util.getCodeQLDatabasePath(config, language)); | |
const spec = env["ODASA_TRACER_CONFIGURATION"]; | |
const info = { spec, env: {} }; | |
// Extract critical tracer variables from the environment | |
for (const entry of Object.entries(env)) { | |
const key = entry[0]; | |
const value = entry[1]; | |
// skip ODASA_TRACER_CONFIGURATION as it is handled separately | |
if (key === "ODASA_TRACER_CONFIGURATION") { | |
continue; | |
} | |
// skip undefined values | |
if (typeof value === "undefined") { | |
continue; | |
} | |
// Keep variables that do not exist in current environment. In addition always keep | |
// critical and CODEQL_ variables | |
if (typeof process.env[key] === "undefined" || | |
CRITICAL_TRACER_VARS.has(key) || | |
key.startsWith("CODEQL_")) { | |
info.env[key] = value; | |
} | |
} | |
return info; | |
} | |
exports.getTracerConfigForLanguage = getTracerConfigForLanguage; | |
function concatTracerConfigs(tracerConfigs, config, writeBothEnvironments = false) { | |
// A tracer config is a map containing additional environment variables and a tracer 'spec' file. | |
// A tracer 'spec' file has the following format [log_file, number_of_blocks, blocks_text] | |
// Merge the environments | |
const env = {}; | |
let copyExecutables = false; | |
let envSize = 0; | |
for (const v of Object.values(tracerConfigs)) { | |
for (const e of Object.entries(v.env)) { | |
const name = e[0]; | |
const value = e[1]; | |
// skip SEMMLE_COPY_EXECUTABLES_ROOT as it is handled separately | |
if (name === "SEMMLE_COPY_EXECUTABLES_ROOT") { | |
copyExecutables = true; | |
} | |
else if (name in env) { | |
if (env[name] !== value) { | |
throw Error(`Incompatible values in environment parameter ${name}: ${env[name]} and ${value}`); | |
} | |
} | |
else { | |
env[name] = value; | |
envSize += 1; | |
} | |
} | |
} | |
// Concatenate spec files into a new spec file | |
const languages = Object.keys(tracerConfigs); | |
const cppIndex = languages.indexOf("cpp"); | |
// Make sure cpp is the last language, if it's present since it must be concatenated last | |
if (cppIndex !== -1) { | |
const lastLang = languages[languages.length - 1]; | |
languages[languages.length - 1] = languages[cppIndex]; | |
languages[cppIndex] = lastLang; | |
} | |
const totalLines = []; | |
let totalCount = 0; | |
for (const lang of languages) { | |
const lines = fs | |
.readFileSync(tracerConfigs[lang].spec, "utf8") | |
.split(/\r?\n/); | |
const count = parseInt(lines[1], 10); | |
totalCount += count; | |
totalLines.push(...lines.slice(2)); | |
} | |
const newLogFilePath = path.resolve(config.tempDir, "compound-build-tracer.log"); | |
const spec = path.resolve(config.tempDir, "compound-spec"); | |
const compoundTempFolder = path.resolve(config.tempDir, "compound-temp"); | |
const newSpecContent = [ | |
newLogFilePath, | |
totalCount.toString(10), | |
...totalLines, | |
]; | |
if (copyExecutables) { | |
env["SEMMLE_COPY_EXECUTABLES_ROOT"] = compoundTempFolder; | |
envSize += 1; | |
} | |
fs.writeFileSync(spec, newSpecContent.join("\n")); | |
if (writeBothEnvironments || process.platform !== "win32") { | |
// Prepare the content of the compound environment file on Unix | |
let buffer = Buffer.alloc(4); | |
buffer.writeInt32LE(envSize, 0); | |
for (const e of Object.entries(env)) { | |
const key = e[0]; | |
const value = e[1]; | |
const lineBuffer = Buffer.from(`${key}=${value}\0`, "utf8"); | |
const sizeBuffer = Buffer.alloc(4); | |
sizeBuffer.writeInt32LE(lineBuffer.length, 0); | |
buffer = Buffer.concat([buffer, sizeBuffer, lineBuffer]); | |
} | |
// Write the compound environment for Unix | |
const envPath = `${spec}.environment`; | |
fs.writeFileSync(envPath, buffer); | |
} | |
if (writeBothEnvironments || process.platform === "win32") { | |
// Prepare the content of the compound environment file on Windows | |
let bufferWindows = Buffer.alloc(0); | |
let length = 0; | |
for (const e of Object.entries(env)) { | |
const key = e[0]; | |
const value = e[1]; | |
const string = `${key}=${value}\0`; | |
length += string.length; | |
const lineBuffer = Buffer.from(string, "utf16le"); | |
bufferWindows = Buffer.concat([bufferWindows, lineBuffer]); | |
} | |
const sizeBuffer = Buffer.alloc(4); | |
sizeBuffer.writeInt32LE(length + 1, 0); // Add one for trailing null character marking end | |
const trailingNull = Buffer.from(`\0`, "utf16le"); | |
bufferWindows = Buffer.concat([sizeBuffer, bufferWindows, trailingNull]); | |
// Write the compound environment for Windows | |
const envPathWindows = `${spec}.win32env`; | |
fs.writeFileSync(envPathWindows, bufferWindows); | |
} | |
return { env, spec }; | |
} | |
exports.concatTracerConfigs = concatTracerConfigs; | |
async function getCombinedTracerConfig(config, codeql) { | |
// Abort if there are no traced languages as there's nothing to do | |
const tracedLanguages = config.languages.filter(languages_1.isTracedLanguage); | |
if (tracedLanguages.length === 0) { | |
return undefined; | |
} | |
let mainTracerConfig; | |
if (await (0, util_1.codeQlVersionAbove)(codeql, codeql_1.CODEQL_VERSION_NEW_TRACING)) { | |
mainTracerConfig = await getTracerConfigForCluster(config); | |
} | |
else { | |
// Get all the tracer configs and combine them together | |
const tracedLanguageConfigs = {}; | |
for (const language of tracedLanguages) { | |
tracedLanguageConfigs[language] = await getTracerConfigForLanguage(codeql, config, language); | |
} | |
mainTracerConfig = concatTracerConfigs(tracedLanguageConfigs, config); | |
// Add a couple more variables | |
mainTracerConfig.env["ODASA_TRACER_CONFIGURATION"] = mainTracerConfig.spec; | |
const codeQLDir = path.dirname(codeql.getPath()); | |
if (process.platform === "darwin") { | |
mainTracerConfig.env["DYLD_INSERT_LIBRARIES"] = path.join(codeQLDir, "tools", "osx64", "libtrace.dylib"); | |
} | |
else if (process.platform !== "win32") { | |
mainTracerConfig.env["LD_PRELOAD"] = path.join(codeQLDir, "tools", "linux64", "${LIB}trace.so"); | |
} | |
} | |
// On macos it's necessary to prefix the build command with the runner executable | |
// on order to trace when System Integrity Protection is enabled. | |
// The executable also exists and works for other platforms so we output this env | |
// var with a path to the runner regardless so it's always available. | |
const runnerExeName = process.platform === "win32" ? "runner.exe" : "runner"; | |
mainTracerConfig.env["CODEQL_RUNNER"] = path.join(mainTracerConfig.env["CODEQL_DIST"], "tools", mainTracerConfig.env["CODEQL_PLATFORM"], runnerExeName); | |
return mainTracerConfig; | |
} | |
exports.getCombinedTracerConfig = getCombinedTracerConfig; | |
//# sourceMappingURL=tracer-config.js.map |