Update ERIS and record URN mappings in ELF notes
This commit is contained in:
parent
256fac99ad
commit
d2bf5375d8
97
flake.lock
97
flake.lock
|
@ -3,14 +3,16 @@
|
||||||
"eris": {
|
"eris": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nimble": "nimble",
|
"nimble": "nimble",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1652741572,
|
"lastModified": 1665183375,
|
||||||
"narHash": "sha256-c+8/yxYckS2PrA7SoEmEr6dqDwzQnw1Hz2LhJBDN4DA=",
|
"narHash": "sha256-soRRiLo2fGGiup7vK3nKUQ7rvJQWt1d941uD+wGT2Oc=",
|
||||||
"ref": "master",
|
"ref": "refs/heads/trunk",
|
||||||
"rev": "27bd39452ec548744e14a3169e85602340125851",
|
"rev": "c190cc13e5f2518913a266180a26b54d39dbcc87",
|
||||||
"revCount": 10,
|
"revCount": 30,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://codeberg.org/eris/nix-eris"
|
"url": "https://codeberg.org/eris/nix-eris"
|
||||||
},
|
},
|
||||||
|
@ -21,31 +23,17 @@
|
||||||
},
|
},
|
||||||
"nimble": {
|
"nimble": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": [
|
||||||
|
"eris",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1652579357,
|
"lastModified": 1662949370,
|
||||||
"narHash": "sha256-hy50WWc872o177Ok4GQoMOi3La2DlzJyEboOD4iGE8Q=",
|
"narHash": "sha256-tNGaNy/0iOS54wYK7g7AQIpArMg8XqCQsAisoZ7Dg4U=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "flake-nimble",
|
"repo": "flake-nimble",
|
||||||
"rev": "a48df7c801b1da371492f5689dfbd5f6a128a6c2",
|
"rev": "54dd3e91c0b61ea63eb4065f95b97f3f0fc98b06",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nimble",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nimble_2": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs_3"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1652924471,
|
|
||||||
"narHash": "sha256-8lxEUhy5XXLaMy8J8eWwiufHUZpTnrI4ykS5lekPq3Y=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "flake-nimble",
|
|
||||||
"rev": "c3993134d3d8e6a601311fb662b2698b26b43575",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -55,53 +43,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1641555862,
|
"lastModified": 1665079737,
|
||||||
"narHash": "sha256-AJK1Q5djPXs/ba3K6gHsVAer9yDPVLic78ZIDsFSkHU=",
|
"narHash": "sha256-mbi/+D73l2VXmiIJzh1oNjohrh+o2MrPblEGzaR7IiI=",
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "d1acd89e0116ff88eba80541027429fc922612e9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1652692103,
|
|
||||||
"narHash": "sha256-ygRLh8g0F/WkVCSfQcxMoVaaD45i6Ky+f+b4wCOazag=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "556ce9a40abde33738e6c9eac65f965a8be3b623",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_3": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1641555862,
|
|
||||||
"narHash": "sha256-AJK1Q5djPXs/ba3K6gHsVAer9yDPVLic78ZIDsFSkHU=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "d1acd89e0116ff88eba80541027429fc922612e9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_4": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1653521725,
|
|
||||||
"narHash": "sha256-JO3Ni/gV4+7eloZrXW0hY7PNfy5TGVJWOPEhtnV9ugQ=",
|
|
||||||
"owner": "ehmry",
|
"owner": "ehmry",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2ec153670397dd3393e6b79d3057c0279539eb10",
|
"rev": "f971220848e4f9efe39667bc986f10e378a8b877",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -114,8 +60,11 @@
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"eris": "eris",
|
"eris": "eris",
|
||||||
"nimble": "nimble_2",
|
"nimble": [
|
||||||
"nixpkgs": "nixpkgs_4"
|
"eris",
|
||||||
|
"nimble"
|
||||||
|
],
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
description = "Nix flavored Genode distribution";
|
description = "Nix flavored Genode distribution";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
eris.url = "git+https://codeberg.org/eris/nix-eris";
|
eris = {
|
||||||
|
url = "git+https://codeberg.org/eris/nix-eris";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
nimble.follows = "eris/nimble";
|
||||||
nixpkgs.url = "github:ehmry/nixpkgs/sigil-21.11";
|
nixpkgs.url = "github:ehmry/nixpkgs/sigil-21.11";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +59,7 @@
|
||||||
# Overlay of adjustments applied to Nixpkgs as well as
|
# Overlay of adjustments applied to Nixpkgs as well as
|
||||||
# the "genodePackages" set which the "packages"
|
# the "genodePackages" set which the "packages"
|
||||||
# output of this flake is taken.
|
# output of this flake is taken.
|
||||||
import ./overlay { flake = self; };
|
import ./overlay;
|
||||||
|
|
||||||
lib =
|
lib =
|
||||||
# Local utilities merged with the Nixpkgs lib
|
# Local utilities merged with the Nixpkgs lib
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
{ flake }:
|
|
||||||
final: prev:
|
final: prev:
|
||||||
with prev;
|
with prev;
|
||||||
|
|
||||||
|
@ -99,6 +98,8 @@ in nullPkgs // {
|
||||||
# The Genode-only packages.
|
# The Genode-only packages.
|
||||||
import ../packages { inherit final prev; };
|
import ../packages { inherit final prev; };
|
||||||
|
|
||||||
|
getdns = overrideHost { doxygen = null; } prev.getdns;
|
||||||
|
|
||||||
grub2 =
|
grub2 =
|
||||||
# No need for a Genode build of GRUB.
|
# No need for a Genode build of GRUB.
|
||||||
if stdenv.targetPlatform.isGenode then
|
if stdenv.targetPlatform.isGenode then
|
||||||
|
@ -168,17 +169,18 @@ in nullPkgs // {
|
||||||
# Packages from the Nimble flake with adjustments.
|
# Packages from the Nimble flake with adjustments.
|
||||||
prev.nimPackages.overrideScope' (_: prev': {
|
prev.nimPackages.overrideScope' (_: prev': {
|
||||||
|
|
||||||
dhall = with prev'; buildNimPackage rec {
|
dhall = with prev';
|
||||||
name = "dhall";
|
buildNimPackage rec {
|
||||||
version = "0.1.0";
|
pname = "dhall";
|
||||||
src = prev.fetchFromSourcehut {
|
version = "20221007";
|
||||||
owner = "~ehmry";
|
src = prev.fetchFromSourcehut {
|
||||||
repo = "dhall-nim";
|
owner = "~ehmry";
|
||||||
rev = version;
|
repo = "${pname}-nim";
|
||||||
hash = "sha256-AhGD/h61Yqiq80woD8bfrvwuTjqCPGYCmUFhK5xFur4=";
|
rev = version;
|
||||||
|
hash = "sha256-wDD9ZRQ6FcQrPLFMCFJcsBIXFzE3wLYqL12AF1KPE0g=";
|
||||||
|
};
|
||||||
|
buildInputs = [ bigints cbor ];
|
||||||
};
|
};
|
||||||
buildInputs = [ bigints cbor ];
|
|
||||||
};
|
|
||||||
|
|
||||||
genode = prev'.genode.overrideAttrs (attrs: rec {
|
genode = prev'.genode.overrideAttrs (attrs: rec {
|
||||||
version = "20.11.1";
|
version = "20.11.1";
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
{ buildNimPackage, patchelf, base32, bigints, cbor, dhall, eris }:
|
{ lib, buildNimPackage, bintools-unwrapped, patchelf, base32, bigints, cbor, dhall, eris }:
|
||||||
|
|
||||||
buildNimPackage {
|
buildNimPackage {
|
||||||
name = "eris_patch";
|
name = "eris_patch";
|
||||||
buildInputs = [ base32 bigints cbor dhall eris ];
|
buildInputs = [ base32 bigints cbor dhall eris ];
|
||||||
inherit patchelf;
|
patchelf = "${lib.getBin patchelf}/bin/patchelf";
|
||||||
|
objcopy = "${lib.getBin bintools-unwrapped}/bin/objcopy";
|
||||||
unpackPhase = "install -D ${./eris_patch.nim} ./src/eris_patch.nim";
|
unpackPhase = "install -D ${./eris_patch.nim} ./src/eris_patch.nim";
|
||||||
nimBinOnly = true;
|
nimBinOnly = true;
|
||||||
preConfigure = ''
|
preConfigure = ''
|
||||||
|
|
|
@ -1,6 +1,29 @@
|
||||||
import std/[asyncdispatch, deques, json, os, osproc, streams, strutils, tables]
|
import std/[asyncdispatch, deques, json, os, osproc, streams, strutils, tables]
|
||||||
import dhall/[render, terms]
|
import cbor, dhall/[render, terms], eris
|
||||||
import eris
|
|
||||||
|
const selfDescribedCbor = 55799
|
||||||
|
|
||||||
|
proc writeErisLinks(path: string; node: CborNode) =
|
||||||
|
# Inspired by "Package Metadata for Core Files"
|
||||||
|
# - https://systemd.io/COREDUMP_PACKAGE_METADATA/
|
||||||
|
# - http://netbsd.org/docs/kernel/elf-notes.html
|
||||||
|
const name = "Sigil\x00"
|
||||||
|
var links = newStringStream()
|
||||||
|
links.writeCborTag(selfDescribedCbor)
|
||||||
|
links.writeCbor(node)
|
||||||
|
var file = openFileStream(path, fmWrite)
|
||||||
|
file.write(uint32 name.len)
|
||||||
|
file.write(uint32 links.data.len)
|
||||||
|
file.write(uint32 1)
|
||||||
|
file.write(name)
|
||||||
|
while (file.getPosition and 3) != 0: file.write(byte 0)
|
||||||
|
file.write(links.data)
|
||||||
|
while (file.getPosition and 3) != 0: file.write(byte 0)
|
||||||
|
close(file)
|
||||||
|
|
||||||
|
proc toCbor(cap: ErisCap): CborNode =
|
||||||
|
result = initCborBytes(cap.bytes)
|
||||||
|
result.tag = erisCborTag
|
||||||
|
|
||||||
proc toDhall(js: JsonNode): Value =
|
proc toDhall(js: JsonNode): Value =
|
||||||
case js.kind
|
case js.kind
|
||||||
|
@ -13,14 +36,6 @@ proc toDhall(js: JsonNode): Value =
|
||||||
else:
|
else:
|
||||||
raiseAssert "unhandled JSON value"
|
raiseAssert "unhandled JSON value"
|
||||||
|
|
||||||
if getEnv("dontErisPatch") != "": quit 0
|
|
||||||
|
|
||||||
let
|
|
||||||
patchelf = getEnv("ERIS_PATCHELF", "patchelf")
|
|
||||||
nixStore = getEnv("NIX_STORE", "/nix/store")
|
|
||||||
jsonManifestSubPath = "nix-support" / "eris-manifest.json"
|
|
||||||
dhallManifestSubPath = "nix-support" / "eris-manifest.dhall"
|
|
||||||
|
|
||||||
proc isElf(path: string): bool =
|
proc isElf(path: string): bool =
|
||||||
var magic: array[4, char]
|
var magic: array[4, char]
|
||||||
let file = open(path)
|
let file = open(path)
|
||||||
|
@ -28,176 +43,224 @@ proc isElf(path: string): bool =
|
||||||
close(file)
|
close(file)
|
||||||
magic == [0x7f.char, 'E', 'L', 'F']
|
magic == [0x7f.char, 'E', 'L', 'F']
|
||||||
|
|
||||||
type PendingFile = ref object
|
proc main =
|
||||||
outputRoot, filePath: string
|
var generateManifests, generateNotes, addNotes, runPatchelf: bool
|
||||||
replacements: Table[string, string]
|
for arg in commandLineParams():
|
||||||
|
case arg
|
||||||
|
of "--add-notes": addNotes = true
|
||||||
|
of "--run-patchelf": runPatchelf = true
|
||||||
|
of "--generate-manifests": generateManifests = true
|
||||||
|
of "--generate-notes": generateNotes = true
|
||||||
|
|
||||||
var
|
if getEnv("dontErisPatch") != "": quit 0
|
||||||
outputManifests = initTable[string, JsonNode]()
|
let
|
||||||
pendingFiles = initDeque[PendingFile]()
|
patchelf = getEnv("ERIS_PATCHELF", "patchelf")
|
||||||
failed = false
|
objcopy = getEnv("ERIS_OBJCOPY", "objcopy")
|
||||||
for outputName in getEnv("outputs").splitWhitespace:
|
nixStore = getEnv("NIX_STORE", "/nix/store")
|
||||||
let outputRoot = getEnv(outputName)
|
jsonManifestSubPath = "nix-support" / "eris-manifest.json"
|
||||||
if fileExists(outputRoot / jsonManifestSubPath):
|
dhallManifestSubPath = "nix-support" / "eris-manifest.dhall"
|
||||||
echo "Not running ERIS patch hook again"
|
|
||||||
quit 0
|
|
||||||
outputManifests[outputRoot] = newJObject()
|
|
||||||
|
|
||||||
let buildInputs = getEnv("buildInputs").splitWhitespace
|
type PendingFile = ref object
|
||||||
|
outputRoot, filePath: string
|
||||||
|
replacements: Table[string, string]
|
||||||
|
erisLinks: CborNode
|
||||||
|
|
||||||
|
var
|
||||||
|
outputManifests = initTable[string, JsonNode]()
|
||||||
|
pendingFiles = initDeque[PendingFile]()
|
||||||
|
failed = false
|
||||||
|
if getEnv("outputs") == "":
|
||||||
|
quit """package $outputs not set in environment"""
|
||||||
|
for outputName in getEnv("outputs").splitWhitespace:
|
||||||
|
if getEnv(outputName) == "":
|
||||||
|
quit("package $" & outputName & " not set in environment")
|
||||||
|
let outputRoot = getEnv(outputName)
|
||||||
|
if fileExists(outputRoot / jsonManifestSubPath):
|
||||||
|
stderr.writeLine "Not running ERIS patch hook again"
|
||||||
|
quit 0
|
||||||
|
outputManifests[outputRoot] = newJObject()
|
||||||
|
|
||||||
|
let buildInputs = getEnv("buildInputs").splitWhitespace
|
||||||
|
|
||||||
|
proc resolveNeed(rpath: seq[string]; need: string): string =
|
||||||
|
if need.isAbsolute:
|
||||||
|
return need
|
||||||
|
for libdir in rpath:
|
||||||
|
let absNeed = libdir / need
|
||||||
|
if fileExists(absNeed):
|
||||||
|
return absNeed
|
||||||
|
for outputRoot in outputManifests.keys:
|
||||||
|
for relPath in [need, "lib" / need]:
|
||||||
|
let absNeed = outputRoot / relPath
|
||||||
|
if fileExists(absNeed):
|
||||||
|
return absNeed
|
||||||
|
for buildInput in buildInputs:
|
||||||
|
for relPath in [need, "lib" / need]:
|
||||||
|
let absNeed = buildInput / relPath
|
||||||
|
if fileExists(absNeed):
|
||||||
|
return absNeed
|
||||||
|
|
||||||
|
proc resolveFile(outputRoot, filePath: string): PendingFile =
|
||||||
|
result = PendingFile(
|
||||||
|
outputRoot: outputRoot,
|
||||||
|
filePath: filePath,
|
||||||
|
replacements: initTable[string, string](8),
|
||||||
|
erisLinks: initCborMap())
|
||||||
|
let needs = splitWhitespace(execProcess(
|
||||||
|
patchelf, args = ["--print-needed", filePath], options = {poUsePath}))
|
||||||
|
let rpath = splitWhitespace(execProcess(
|
||||||
|
patchelf, args = ["--print-rpath", filePath], options = {poUsePath}))
|
||||||
|
for need in needs:
|
||||||
|
if need == "ld.lib.so" or need.startsWith("urn:"): continue
|
||||||
|
result.replacements[need] = resolveNeed(rpath, need)
|
||||||
|
|
||||||
|
var capCache = initTable[string, ErisCap]()
|
||||||
|
|
||||||
|
proc fileCap(filePath: string): ErisCap =
|
||||||
|
## Determine the ERIS read capabililty for ``filePath``.
|
||||||
|
if capCache.hasKey(filePath):
|
||||||
|
result = capCache[filePath]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
let str = openFileStream(filePath)
|
||||||
|
result = waitFor encode(newDiscardStore(), str, convergentMode)
|
||||||
|
capCache["filePath"] = result
|
||||||
|
close(str)
|
||||||
|
except:
|
||||||
|
stderr.writeLine("failed to read \"", filePath, "\"")
|
||||||
|
quit 1
|
||||||
|
|
||||||
|
var closureCache = initTable[string, TableRef[string, ErisCap]]()
|
||||||
|
|
||||||
|
proc fileClosure(filePath: string): TableRef[string, ErisCap] =
|
||||||
|
## Recusively find the dependency closure of ``filePath``.
|
||||||
|
let filePath = expandFilename filePath
|
||||||
|
if closureCache.hasKey(filePath):
|
||||||
|
result = closureCache[filePath]
|
||||||
|
else:
|
||||||
|
result = newTable[string, ErisCap]()
|
||||||
|
var storePath = filePath
|
||||||
|
for p in parentDirs(filePath):
|
||||||
|
# find the top directory of the ``filePath`` derivation
|
||||||
|
if p == nixStore: break
|
||||||
|
storePath = p
|
||||||
|
if storePath.startsWith nixStore:
|
||||||
|
# read the closure manifest of the dependency
|
||||||
|
let manifestPath = storePath / jsonManifestSubPath
|
||||||
|
if fileExists(manifestPath):
|
||||||
|
let
|
||||||
|
manifest = parseFile(manifestPath)
|
||||||
|
entry = manifest[filePath.extractFilename]
|
||||||
|
for path, urn in entry["closure"].pairs:
|
||||||
|
result[path] = parseErisUrn urn.getStr
|
||||||
|
let otherClosure = fileClosure(path)
|
||||||
|
for otherPath, otherCap in otherClosure.pairs:
|
||||||
|
# merge the closure of the dependency
|
||||||
|
result[otherPath] = otherCap
|
||||||
|
closureCache[filePath] = result
|
||||||
|
|
||||||
proc resolveNeed(rpath: seq[string]; need: string): string =
|
|
||||||
if need.isAbsolute:
|
|
||||||
return need
|
|
||||||
for libdir in rpath:
|
|
||||||
let absNeed = libdir / need
|
|
||||||
if fileExists(absNeed):
|
|
||||||
return absNeed
|
|
||||||
for outputRoot in outputManifests.keys:
|
for outputRoot in outputManifests.keys:
|
||||||
for relPath in [need, "lib" / need]:
|
let manifestPath = outputRoot / jsonManifestSubPath
|
||||||
let absNeed = outputRoot / relPath
|
if fileExists manifestPath: continue
|
||||||
if fileExists(absNeed):
|
for filePath in walkDirRec(outputRoot, relative = false):
|
||||||
return absNeed
|
# Populate the queue of files to patch
|
||||||
for buildInput in buildInputs:
|
if filePath.isElf:
|
||||||
for relPath in [need, "lib" / need]:
|
pendingFiles.addLast(resolveFile(outputRoot, filePath))
|
||||||
let absNeed = buildInput / relPath
|
|
||||||
if fileExists(absNeed):
|
|
||||||
return absNeed
|
|
||||||
|
|
||||||
proc resolveFile(outputRoot, filePath: string): PendingFile =
|
var
|
||||||
result = PendingFile(
|
prevLen = pendingFiles.len
|
||||||
outputRoot: outputRoot,
|
prevPrevLen = prevLen.succ
|
||||||
filePath: filePath,
|
# used to detect reference cycles
|
||||||
replacements: initTable[string, string](8))
|
while pendingFiles.len != 0:
|
||||||
let needs = splitWhitespace(execProcess(
|
block selfReferenceCheck:
|
||||||
patchelf, args = ["--print-needed", filePath], options = {poUsePath}))
|
# process the files that have been collected
|
||||||
let rpath = splitWhitespace(execProcess(
|
# taking care not to take a the URN of an
|
||||||
patchelf, args = ["--print-rpath", filePath], options = {poUsePath}))
|
# unprocessed file
|
||||||
for need in needs:
|
let
|
||||||
if need == "ld.lib.so" or need.startsWith("urn:"): continue
|
pendingFile = pendingFiles.popFirst()
|
||||||
result.replacements[need] = resolveNeed(rpath, need)
|
filePath = pendingFile.filePath
|
||||||
|
for need, replacementPath in pendingFile.replacements.pairs:
|
||||||
var capCache = initTable[string, ErisCap]()
|
# search for self-references
|
||||||
|
if replacementPath == "":
|
||||||
proc fileUrn(filePath: string): string =
|
stderr.writeLine need, " not found for ", filePath
|
||||||
## Determine the ERIS URN for ``filePath``.
|
failed = true
|
||||||
var cap: ErisCap
|
continue
|
||||||
if capCache.hasKey(filePath):
|
for outputRoot in outputManifests.keys:
|
||||||
cap = capCache[filePath]
|
if replacementPath.startsWith(outputRoot):
|
||||||
else:
|
for other in pendingFiles.items:
|
||||||
try:
|
stderr.writeLine "compare for self-reference:"
|
||||||
let blockSize = if getFileSize(filePath) < (16 shl 10):
|
stderr.writeLine '\t', replacementPath
|
||||||
bs1k
|
stderr.writeLine '\t', other.filePath
|
||||||
else:
|
if replacementPath == other.filePath:
|
||||||
bs32k
|
stderr.writeLine "defering patch of ", filePath, " with reference to ", other.filePath
|
||||||
let str = openFileStream(filePath)
|
pendingFiles.addLast(pendingFile)
|
||||||
cap = waitFor encode(newDiscardStore(), blockSize, str)
|
break selfReferenceCheck
|
||||||
capCache["filePath"] = cap
|
var
|
||||||
close(str)
|
closure = newJObject()
|
||||||
except:
|
replaceCmd = patchelf & " --set-rpath '' " & filePath
|
||||||
stderr.writeLine("failed to read \"", filePath, "\"")
|
for need, replacementPath in pendingFile.replacements.pairs:
|
||||||
quit 1
|
if replacementPath == "": continue
|
||||||
$cap # & "#" & encodeUrl(extractFilename(filePath), usePlus = false)
|
|
||||||
|
|
||||||
var closureCache = initTable[string, TableRef[string, string]]()
|
|
||||||
|
|
||||||
proc fileClosure(filePath: string): TableRef[string, string] =
|
|
||||||
## Recusively find the dependency closure of ``filePath``.
|
|
||||||
let filePath = expandFilename filePath
|
|
||||||
if closureCache.hasKey(filePath):
|
|
||||||
result = closureCache[filePath]
|
|
||||||
else:
|
|
||||||
result = newTable[string, string]()
|
|
||||||
var storePath = filePath
|
|
||||||
for p in parentDirs(filePath):
|
|
||||||
# find the top directory of the ``filePath`` derivation
|
|
||||||
if p == nixStore: break
|
|
||||||
storePath = p
|
|
||||||
if storePath.startsWith nixStore:
|
|
||||||
# read the closure manifest of the dependency
|
|
||||||
let manifestPath = storePath / jsonManifestSubPath
|
|
||||||
if fileExists(manifestPath):
|
|
||||||
let
|
let
|
||||||
manifest = parseFile(manifestPath)
|
cap = fileCap(replacementPath)
|
||||||
entry = manifest[filePath.extractFilename]
|
urn = $cap
|
||||||
for path, cap in entry["closure"].pairs:
|
stderr.writeLine "replace reference to ", need, " with ", urn
|
||||||
result[path] = cap.getStr
|
closure[replacementPath] = %urn
|
||||||
let otherClosure = fileClosure(path)
|
pendingFile.erisLinks[ replacementPath.toCbor] = cap.toCbor
|
||||||
for otherPath, otherCap in otherClosure.pairs:
|
replaceCmd.add(" --replace-needed $# $#" % [need, urn])
|
||||||
# merge the closure of the dependency
|
for path, cap in fileClosure(replacementPath).pairs:
|
||||||
result[otherPath] = otherCap
|
closure[path] = %($cap)
|
||||||
closureCache[filePath] = result
|
pendingFile.erisLinks[path.toCbor] = cap.toCbor
|
||||||
|
|
||||||
for outputRoot in outputManifests.keys:
|
if runPatchelf and pendingFile.replacements.len != 0:
|
||||||
let manifestPath = outputRoot / jsonManifestSubPath
|
let exitCode = execCmd(replaceCmd)
|
||||||
if fileExists manifestPath: continue
|
if exitCode != 0:
|
||||||
for filePath in walkDirRec(outputRoot, relative = false):
|
stderr.writeLine "Patchelf failed - ", replaceCmd
|
||||||
# Populate the queue of files to patch
|
quit exitCode
|
||||||
if filePath.isElf:
|
|
||||||
pendingFiles.addLast(resolveFile(outputRoot, filePath))
|
|
||||||
|
|
||||||
var
|
let notePath = getEnv("TMPDIR", ".") / "eris-links.note"
|
||||||
prevLen = pendingFiles.len
|
if generateNotes or addNotes:
|
||||||
prevPrevLen = prevLen.succ
|
if generateNotes:
|
||||||
# used to detect reference cycles
|
stderr.writeLine("writing .notes.eris-links section to ", notePath)
|
||||||
while pendingFiles.len != 0:
|
sort(pendingFile.erisLinks)
|
||||||
block selfReferenceCheck:
|
writeErisLinks(notePath, pendingFile.erisLinks)
|
||||||
# process the files that have been collected
|
if addNotes:
|
||||||
# taking care not to take a the URN of an
|
# Modify the file with objcopy last because binutils surely
|
||||||
# unprocessed file
|
# has a more conventional interpretation of the ELF standard
|
||||||
let
|
# than patchelf.
|
||||||
pendingFile = pendingFiles.popFirst()
|
let tmpFile = pendingFile.filePath & ".with-note"
|
||||||
filePath = pendingFile.filePath
|
let objcopyCommand = [
|
||||||
for need, replacementPath in pendingFile.replacements.pairs:
|
objcopy,
|
||||||
# search for self-references
|
"--add-section .note.eris-links=" & notePath,
|
||||||
if replacementPath == "":
|
"--set-section-flags .note.eris-links=noload,readonly",
|
||||||
echo need, " not found for ", filePath
|
pendingFile.filePath, tmpfile]
|
||||||
failed = true
|
let exitCode = execCmd(objcopyCommand.join(" "))
|
||||||
continue
|
if exitCode != 0:
|
||||||
for outputRoot in outputManifests.keys:
|
quit("Adding note to $1 failed" % pendingFile.filePath)
|
||||||
if replacementPath.startsWith(outputRoot):
|
moveFile(tmpFile, pendingFile.filePath)
|
||||||
for other in pendingFiles.items:
|
|
||||||
echo "compare for self-reference:"
|
|
||||||
echo '\t', replacementPath
|
|
||||||
echo '\t', other.filePath
|
|
||||||
if replacementPath == other.filePath:
|
|
||||||
echo "defering patch of ", filePath, " with reference to ", other.filePath
|
|
||||||
pendingFiles.addLast(pendingFile)
|
|
||||||
break selfReferenceCheck
|
|
||||||
var
|
|
||||||
closure = newJObject()
|
|
||||||
replaceCmd = patchelf & " --set-rpath '' " & filePath
|
|
||||||
for need, replacementPath in pendingFile.replacements.pairs:
|
|
||||||
if replacementPath == "": continue
|
|
||||||
let urn = fileUrn(replacementPath)
|
|
||||||
echo "replace reference to ", need, " with ", urn
|
|
||||||
replaceCmd.add(" --replace-needed $# $#" % [need, urn])
|
|
||||||
closure[replacementPath] = %urn
|
|
||||||
for path, urn in fileClosure(replacementPath).pairs:
|
|
||||||
closure[path] = %urn
|
|
||||||
if pendingFile.replacements.len != 0:
|
|
||||||
let exitCode = execCmd(replaceCmd)
|
|
||||||
if exitCode != 0:
|
|
||||||
echo "Patchelf failed - ", replaceCmd
|
|
||||||
quit exitCode
|
|
||||||
outputManifests[pendingFile.outputRoot][filePath.extractFilename] = %* {
|
|
||||||
"cap": fileUrn(filePath),
|
|
||||||
"closure": closure,
|
|
||||||
"path": filePath
|
|
||||||
}
|
|
||||||
if pendingFiles.len == prevPrevLen:
|
|
||||||
failed = true
|
|
||||||
echo "reference cycle detected in the following:"
|
|
||||||
for remain in pendingFiles.items:
|
|
||||||
echo '\t', " ", remain.filePath
|
|
||||||
break
|
|
||||||
prevPrevLen = prevLen
|
|
||||||
prevLen = pendingFiles.len
|
|
||||||
|
|
||||||
if failed:
|
outputManifests[pendingFile.outputRoot][filePath.extractFilename] = %* {
|
||||||
quit -1
|
"cap": $fileCap(filePath),
|
||||||
|
"closure": closure,
|
||||||
|
"path": filePath
|
||||||
|
}
|
||||||
|
|
||||||
for outputRoot, manifest in outputManifests:
|
if pendingFiles.len == prevPrevLen:
|
||||||
let supportDir = outputRoot / "nix-support"
|
failed = true
|
||||||
createDir(supportDir)
|
stderr.writeLine "reference cycle detected in the following:"
|
||||||
writeFile(outputRoot / jsonManifestSubPath, $manifest)
|
for remain in pendingFiles.items:
|
||||||
writeFile(outputRoot / dhallManifestSubPath, $(manifest.toDhall))
|
stderr.writeLine '\t', " ", remain.filePath
|
||||||
|
break
|
||||||
|
prevPrevLen = prevLen
|
||||||
|
prevLen = pendingFiles.len
|
||||||
|
|
||||||
|
if failed:
|
||||||
|
quit -1
|
||||||
|
|
||||||
|
if generateManifests:
|
||||||
|
for outputRoot, manifest in outputManifests:
|
||||||
|
let supportDir = outputRoot / "nix-support"
|
||||||
|
createDir(supportDir)
|
||||||
|
writeFile(outputRoot / jsonManifestSubPath, $manifest)
|
||||||
|
writeFile(outputRoot / dhallManifestSubPath, $(manifest.toDhall))
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export ERIS_PATCHELF=@patchelf@/bin/patchelf
|
export ERIS_PATCHELF=@patchelf@
|
||||||
postFixupHooks+=('@out@/bin/eris_patch')
|
export ERIS_OBJCOPY=@objcopy@
|
||||||
|
postFixupHooks+=('@out@/bin/eris_patch --add-notes --generate-manifests --run-patchelf')
|
||||||
|
|
|
@ -24,13 +24,13 @@ let
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
|
||||||
in upstream // {
|
in upstream // (with final; {
|
||||||
|
|
||||||
bender = buildPackages.callPackage ./bender { };
|
bender = buildPackages.callPackage ./bender { };
|
||||||
|
|
||||||
block_router = callPackage ./block_router { };
|
block_router = callPackage ./block_router { };
|
||||||
|
|
||||||
device_manager = callPackage ./device_manager { };
|
device_manager = nimPackages.callPackage ./device_manager { };
|
||||||
|
|
||||||
dhallSigil = dhallPackages.sigil;
|
dhallSigil = dhallPackages.sigil;
|
||||||
|
|
||||||
|
@ -59,4 +59,4 @@ in upstream // {
|
||||||
sha256 = "0dy906ffbw6khkwd05vhppcw2mr4ma0h3b6n52a71cfail87jfnw";
|
sha256 = "0dy906ffbw6khkwd05vhppcw2mr4ma0h3b6n52a71cfail87jfnw";
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
})
|
||||||
|
|
|
@ -1,33 +1,26 @@
|
||||||
{ lib, stdenv, fetchgit, nim, nimblePackages }:
|
{ lib, buildNimPackage, fetchFromSourcehut, genode }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
buildNimPackage rec {
|
||||||
pname = "device_manager";
|
pname = "device_manager";
|
||||||
version = "0.0";
|
version = "0.0";
|
||||||
outputs = [ "out" "dhall" ];
|
outputs = [ "out" "dhall" ];
|
||||||
|
|
||||||
src = fetchgit {
|
src = fetchFromSourcehut {
|
||||||
url = "https://git.sr.ht/~ehmry/${pname}";
|
owner = "~ehmry";
|
||||||
|
repo = pname;
|
||||||
rev = "4ff7d47b83255a437d862d16b8424a3c05e3eab1";
|
rev = "4ff7d47b83255a437d862d16b8424a3c05e3eab1";
|
||||||
sha256 = "0bmcl693w34ayrw77c6gicph43yfjfm800jwj57ryshr9fdh88dq";
|
hash = "sha256-uCEEm0sZap9PkVwCgKqTzg8CL4vPsHN49ooMPpKhrC4=";
|
||||||
};
|
};
|
||||||
|
|
||||||
nimFlags = with nimblePackages;
|
preConfigure = ''
|
||||||
map (lib: "--path:${lib}/src") [ genode ] ++ [ "-d:posix" ];
|
echo 'backend = "cpp"' >> ${pname}.nimble
|
||||||
|
|
||||||
nativeBuildInputs = [ nim ];
|
|
||||||
|
|
||||||
preHook = ''
|
|
||||||
export HOME="$NIX_BUILD_TOP"
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
buildPhase = ''
|
nimDefines = [ "posix" ];
|
||||||
runHook preBuild
|
|
||||||
nim cpp $nimFlags src/$pname
|
|
||||||
runHook postBuild
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
buildInputs = [ genode ];
|
||||||
install -Dt $out/bin src/$pname
|
|
||||||
|
postInstall = ''
|
||||||
install -Dt $dhall config/package.dhall
|
install -Dt $dhall config/package.dhall
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,23 +3,18 @@
|
||||||
machine = { pkgs, ... }: {
|
machine = { pkgs, ... }: {
|
||||||
genode.init.children.test_nim = let
|
genode.init.children.test_nim = let
|
||||||
testNim = with pkgs;
|
testNim = with pkgs;
|
||||||
stdenv.mkDerivation {
|
nimPackages.buildNimPackage {
|
||||||
pname = "test-nim";
|
pname = "test_nim";
|
||||||
inherit (nim-unwrapped) version;
|
inherit (nim) version;
|
||||||
nativeBuildInputs = [ nim ];
|
nimDefines = [ "posix" ];
|
||||||
dontUnpack = true;
|
unpackPhase = ''
|
||||||
dontConfigure = true;
|
mkdir test
|
||||||
buildPhase = ''
|
cd test
|
||||||
export HOME=$NIX_BUILD_TOP
|
echo 'echo "Hello Nim world!"' > test_nim.nim
|
||||||
cat << EOF > test_nim.nim
|
cat << EOF > eris_patch.nimble
|
||||||
echo "Hello Nim world!"
|
backend = "cpp"
|
||||||
|
bin = @[ "test_nim"]
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
nim cpp -d:posix -d:release --gc:orc test_nim
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
install -Dt $out/bin test_nim
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
|
|
Loading…
Reference in New Issue