summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/add-git-hook.sh13
-rwxr-xr-xtools/check-efi-alignment.py36
-rw-r--r--tools/check-version-history.py7
-rw-r--r--tools/command_ignorelist6
-rwxr-xr-xtools/dbus_exporter.py2
-rw-r--r--tools/dbus_ignorelist46
-rwxr-xr-xtools/elf2efi.py252
-rwxr-xr-xtools/git-contrib.sh12
-rwxr-xr-xtools/git-setup.sh16
-rwxr-xr-xtools/make-man-index.py2
-rwxr-xr-xtools/meson-extract-unit-files.py20
-rwxr-xr-xtools/meson-render-jinja2.py9
-rwxr-xr-xtools/meson-vcs-tag.sh33
-rwxr-xr-xtools/update-dbus-docs.py15
-rwxr-xr-xtools/update-distro-hash.py89
-rwxr-xr-xtools/update-man-rules.py1
16 files changed, 346 insertions, 213 deletions
diff --git a/tools/add-git-hook.sh b/tools/add-git-hook.sh
deleted file mode 100755
index 8cff62e..0000000
--- a/tools/add-git-hook.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: LGPL-2.1-or-later
-set -eu
-
-cd "${MESON_SOURCE_ROOT:?}"
-
-if [ ! -f .git/hooks/pre-commit.sample ] || [ -f .git/hooks/pre-commit ]; then
- exit 2 # not needed
-fi
-
-cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit
-chmod +x .git/hooks/pre-commit
-echo 'Activated pre-commit hook'
diff --git a/tools/check-efi-alignment.py b/tools/check-efi-alignment.py
new file mode 100755
index 0000000..26d5f5e
--- /dev/null
+++ b/tools/check-efi-alignment.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# vi: set tw=110 sw=4 ts=4 et:
+
+import sys
+
+try:
+ import pefile
+except ImportError as e:
+ print(str(e), file=sys.stderr)
+ sys.exit(77)
+
+
+def main():
+ pe = pefile.PE(sys.argv[1], fast_load=True)
+
+ for section in pe.sections:
+ name = section.Name.rstrip(b"\x00").decode()
+ file_addr = section.PointerToRawData
+ virt_addr = section.VirtualAddress
+ print(f"{name:10s} file=0x{file_addr:08x} virt=0x{virt_addr:08x}")
+
+ if file_addr % 512 != 0:
+ print(f"File address of {name} section is not aligned to 512 bytes", file=sys.stderr)
+ return 1
+
+ if virt_addr % 512 != 0:
+ print(f"Virt address of {name} section is not aligned to 512 bytes", file=sys.stderr)
+ return 1
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print(f"Usage: {sys.argv[0]} pe-image")
+ sys.exit(1)
+
+ sys.exit(main())
diff --git a/tools/check-version-history.py b/tools/check-version-history.py
index c4d4b3e..d4a87df 100644
--- a/tools/check-version-history.py
+++ b/tools/check-version-history.py
@@ -3,7 +3,12 @@
import os
import sys
-import lxml.etree as tree
+
+try:
+ import lxml.etree as tree
+except ImportError as e:
+ print(str(e), file=sys.stderr)
+ sys.exit(77)
_parser = tree.XMLParser(resolve_entities=False)
tree.set_default_parser(_parser)
diff --git a/tools/command_ignorelist b/tools/command_ignorelist
index 186136d..af694c1 100644
--- a/tools/command_ignorelist
+++ b/tools/command_ignorelist
@@ -169,9 +169,9 @@ systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="Execution Options"
systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="System Identity Options"]/variablelist/varlistentry[term="--uuid="]
systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="Networking Options"]/variablelist/varlistentry[term="--private-network"]
systemd-nspawn.xml /refsect1[title="Options"]/refsect2[title="Image Options"]/variablelist/varlistentry[term="--read-only"]
-systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--create"]
-systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--clean"]
-systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--remove"]
+systemd-tmpfiles.xml /refsect1[title="Commands and options"]/variablelist/varlistentry[term="--create"]
+systemd-tmpfiles.xml /refsect1[title="Commands and options"]/variablelist/varlistentry[term="--clean"]
+systemd-tmpfiles.xml /refsect1[title="Commands and options"]/variablelist/varlistentry[term="--remove"]
systemd-tmpfiles.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--prefix=path"]
systemd.automount.xml /refsect1[title="Options"]/variablelist/varlistentry[term="Where="]
systemd.automount.xml /refsect1[title="Options"]/variablelist/varlistentry[term="DirectoryMode="]
diff --git a/tools/dbus_exporter.py b/tools/dbus_exporter.py
index 819584d..db95a58 100755
--- a/tools/dbus_exporter.py
+++ b/tools/dbus_exporter.py
@@ -36,6 +36,8 @@ def main():
args = parser.parse_args()
args.output.mkdir(exist_ok=True)
+ # Make sure we don't inherit any setgid/setuid bit or such.
+ args.output.chmod(mode=0o755)
for exe in args.executables:
extract_interfaces_xml(args.output, exe)
diff --git a/tools/dbus_ignorelist b/tools/dbus_ignorelist
index d0c2150..71bdad8 100644
--- a/tools/dbus_ignorelist
+++ b/tools/dbus_ignorelist
@@ -82,12 +82,12 @@ org.freedesktop.import1.Manager.ImportTar()
org.freedesktop.import1.Manager.ListTransfers()
org.freedesktop.import1.Manager.PullRaw()
org.freedesktop.import1.Manager.PullTar()
-org.freedesktop.import1.Manager.TransferNew
-org.freedesktop.import1.Manager.TransferRemoved
+org.freedesktop.import1.Manager.TransferNew()
+org.freedesktop.import1.Manager.TransferRemoved()
org.freedesktop.import1.Transfer.Cancel()
org.freedesktop.import1.Transfer.Id
org.freedesktop.import1.Transfer.Local
-org.freedesktop.import1.Transfer.LogMessage
+org.freedesktop.import1.Transfer.LogMessage()
org.freedesktop.import1.Transfer.Progress
org.freedesktop.import1.Transfer.Remote
org.freedesktop.import1.Transfer.Type
@@ -168,8 +168,8 @@ org.freedesktop.login1.Manager.NCurrentSessions
org.freedesktop.login1.Manager.OnExternalPower
org.freedesktop.login1.Manager.PowerOff()
org.freedesktop.login1.Manager.PowerOffWithFlags()
-org.freedesktop.login1.Manager.PrepareForShutdown
-org.freedesktop.login1.Manager.PrepareForSleep
+org.freedesktop.login1.Manager.PrepareForShutdown()
+org.freedesktop.login1.Manager.PrepareForSleep()
org.freedesktop.login1.Manager.PreparingForShutdown
org.freedesktop.login1.Manager.PreparingForSleep
org.freedesktop.login1.Manager.Reboot()
@@ -184,10 +184,10 @@ org.freedesktop.login1.Manager.RuntimeDirectoryInodesMax
org.freedesktop.login1.Manager.RuntimeDirectorySize
org.freedesktop.login1.Manager.ScheduleShutdown()
org.freedesktop.login1.Manager.ScheduledShutdown
-org.freedesktop.login1.Manager.SeatNew
-org.freedesktop.login1.Manager.SeatRemoved
-org.freedesktop.login1.Manager.SessionNew
-org.freedesktop.login1.Manager.SessionRemoved
+org.freedesktop.login1.Manager.SeatNew()
+org.freedesktop.login1.Manager.SeatRemoved()
+org.freedesktop.login1.Manager.SessionNew()
+org.freedesktop.login1.Manager.SessionRemoved()
org.freedesktop.login1.Manager.SessionsMax
org.freedesktop.login1.Manager.SetRebootParameter()
org.freedesktop.login1.Manager.SetRebootToBootLoaderEntry()
@@ -204,8 +204,8 @@ org.freedesktop.login1.Manager.TerminateSession()
org.freedesktop.login1.Manager.TerminateUser()
org.freedesktop.login1.Manager.UnlockSession()
org.freedesktop.login1.Manager.UnlockSessions()
-org.freedesktop.login1.Manager.UserNew
-org.freedesktop.login1.Manager.UserRemoved
+org.freedesktop.login1.Manager.UserNew()
+org.freedesktop.login1.Manager.UserRemoved()
org.freedesktop.login1.Manager.UserStopDelayUSec
org.freedesktop.login1.Manager.WallMessage
org.freedesktop.login1.Seat.ActivateSession()
@@ -237,14 +237,14 @@ org.freedesktop.login1.Session.Lock
org.freedesktop.login1.Session.Lock()
org.freedesktop.login1.Session.LockedHint
org.freedesktop.login1.Session.Name
-org.freedesktop.login1.Session.PauseDevice
+org.freedesktop.login1.Session.PauseDevice()
org.freedesktop.login1.Session.PauseDeviceComplete()
org.freedesktop.login1.Session.ReleaseControl()
org.freedesktop.login1.Session.ReleaseDevice()
org.freedesktop.login1.Session.Remote
org.freedesktop.login1.Session.RemoteHost
org.freedesktop.login1.Session.RemoteUser
-org.freedesktop.login1.Session.ResumeDevice
+org.freedesktop.login1.Session.ResumeDevice()
org.freedesktop.login1.Session.Scope
org.freedesktop.login1.Session.Seat
org.freedesktop.login1.Session.Service
@@ -343,8 +343,8 @@ org.freedesktop.machine1.Manager.GetMachineUIDShift()
org.freedesktop.machine1.Manager.KillMachine()
org.freedesktop.machine1.Manager.ListImages()
org.freedesktop.machine1.Manager.ListMachines()
-org.freedesktop.machine1.Manager.MachineNew
-org.freedesktop.machine1.Manager.MachineRemoved
+org.freedesktop.machine1.Manager.MachineNew()
+org.freedesktop.machine1.Manager.MachineRemoved()
org.freedesktop.machine1.Manager.MapFromMachineGroup()
org.freedesktop.machine1.Manager.MapFromMachineUser()
org.freedesktop.machine1.Manager.MapToMachineGroup()
@@ -653,8 +653,8 @@ org.freedesktop.systemd1.Manager.InitRDUnitsLoadFinishTimestamp
org.freedesktop.systemd1.Manager.InitRDUnitsLoadFinishTimestampMonotonic
org.freedesktop.systemd1.Manager.InitRDUnitsLoadStartTimestamp
org.freedesktop.systemd1.Manager.InitRDUnitsLoadStartTimestampMonotonic
-org.freedesktop.systemd1.Manager.JobNew
-org.freedesktop.systemd1.Manager.JobRemoved
+org.freedesktop.systemd1.Manager.JobNew()
+org.freedesktop.systemd1.Manager.JobRemoved()
org.freedesktop.systemd1.Manager.KExec()
org.freedesktop.systemd1.Manager.KExecWatchdogUSec
org.freedesktop.systemd1.Manager.KernelTimestamp
@@ -696,7 +696,7 @@ org.freedesktop.systemd1.Manager.Reload()
org.freedesktop.systemd1.Manager.ReloadOrRestartUnit()
org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit()
org.freedesktop.systemd1.Manager.ReloadUnit()
-org.freedesktop.systemd1.Manager.Reloading
+org.freedesktop.systemd1.Manager.Reloading()
org.freedesktop.systemd1.Manager.ResetFailed()
org.freedesktop.systemd1.Manager.ResetFailedUnit()
org.freedesktop.systemd1.Manager.RestartUnit()
@@ -717,7 +717,7 @@ org.freedesktop.systemd1.Manager.StartTransientUnit()
org.freedesktop.systemd1.Manager.StartUnit()
org.freedesktop.systemd1.Manager.StartUnitReplace()
org.freedesktop.systemd1.Manager.StartUnitWithFlags()
-org.freedesktop.systemd1.Manager.StartupFinished
+org.freedesktop.systemd1.Manager.StartupFinished()
org.freedesktop.systemd1.Manager.StopUnit()
org.freedesktop.systemd1.Manager.Subscribe()
org.freedesktop.systemd1.Manager.SwitchRoot()
@@ -726,10 +726,10 @@ org.freedesktop.systemd1.Manager.Tainted
org.freedesktop.systemd1.Manager.ThawUnit()
org.freedesktop.systemd1.Manager.TimerSlackNSec
org.freedesktop.systemd1.Manager.TryRestartUnit()
-org.freedesktop.systemd1.Manager.UnitFilesChanged
-org.freedesktop.systemd1.Manager.UnitNew
+org.freedesktop.systemd1.Manager.UnitFilesChanged()
+org.freedesktop.systemd1.Manager.UnitNew()
org.freedesktop.systemd1.Manager.UnitPath
-org.freedesktop.systemd1.Manager.UnitRemoved
+org.freedesktop.systemd1.Manager.UnitRemoved()
org.freedesktop.systemd1.Manager.UnitsLoadFinishTimestamp
org.freedesktop.systemd1.Manager.UnitsLoadFinishTimestampMonotonic
org.freedesktop.systemd1.Manager.UnitsLoadStartTimestamp
@@ -1078,7 +1078,7 @@ org.freedesktop.systemd1.Scope.MemoryLow
org.freedesktop.systemd1.Scope.MemoryMax
org.freedesktop.systemd1.Scope.MemoryMin
org.freedesktop.systemd1.Scope.MemorySwapMax
-org.freedesktop.systemd1.Scope.RequestStop
+org.freedesktop.systemd1.Scope.RequestStop()
org.freedesktop.systemd1.Scope.RestartKillSignal
org.freedesktop.systemd1.Scope.RestrictNetworkInterfaces
org.freedesktop.systemd1.Scope.Result
diff --git a/tools/elf2efi.py b/tools/elf2efi.py
index 54f64fa..cb1a284 100755
--- a/tools/elf2efi.py
+++ b/tools/elf2efi.py
@@ -26,6 +26,7 @@ import hashlib
import io
import os
import pathlib
+import sys
import time
import typing
from ctypes import (
@@ -55,26 +56,26 @@ from elftools.elf.relocation import (
class PeCoffHeader(LittleEndianStructure):
_fields_ = (
- ("Machine", c_uint16),
- ("NumberOfSections", c_uint16),
- ("TimeDateStamp", c_uint32),
+ ("Machine", c_uint16),
+ ("NumberOfSections", c_uint16),
+ ("TimeDateStamp", c_uint32),
("PointerToSymbolTable", c_uint32),
- ("NumberOfSymbols", c_uint32),
+ ("NumberOfSymbols", c_uint32),
("SizeOfOptionalHeader", c_uint16),
- ("Characteristics", c_uint16),
+ ("Characteristics", c_uint16),
)
class PeDataDirectory(LittleEndianStructure):
_fields_ = (
("VirtualAddress", c_uint32),
- ("Size", c_uint32),
+ ("Size", c_uint32),
)
class PeRelocationBlock(LittleEndianStructure):
_fields_ = (
- ("PageRVA", c_uint32),
+ ("PageRVA", c_uint32),
("BlockSize", c_uint32),
)
@@ -86,62 +87,62 @@ class PeRelocationBlock(LittleEndianStructure):
class PeRelocationEntry(LittleEndianStructure):
_fields_ = (
("Offset", c_uint16, 12),
- ("Type", c_uint16, 4),
+ ("Type", c_uint16, 4),
)
class PeOptionalHeaderStart(LittleEndianStructure):
_fields_ = (
- ("Magic", c_uint16),
- ("MajorLinkerVersion", c_uint8),
- ("MinorLinkerVersion", c_uint8),
- ("SizeOfCode", c_uint32),
- ("SizeOfInitializedData", c_uint32),
+ ("Magic", c_uint16),
+ ("MajorLinkerVersion", c_uint8),
+ ("MinorLinkerVersion", c_uint8),
+ ("SizeOfCode", c_uint32),
+ ("SizeOfInitializedData", c_uint32),
("SizeOfUninitializedData", c_uint32),
- ("AddressOfEntryPoint", c_uint32),
- ("BaseOfCode", c_uint32),
+ ("AddressOfEntryPoint", c_uint32),
+ ("BaseOfCode", c_uint32),
)
class PeOptionalHeaderMiddle(LittleEndianStructure):
_fields_ = (
- ("SectionAlignment", c_uint32),
- ("FileAlignment", c_uint32),
+ ("SectionAlignment", c_uint32),
+ ("FileAlignment", c_uint32),
("MajorOperatingSystemVersion", c_uint16),
("MinorOperatingSystemVersion", c_uint16),
- ("MajorImageVersion", c_uint16),
- ("MinorImageVersion", c_uint16),
- ("MajorSubsystemVersion", c_uint16),
- ("MinorSubsystemVersion", c_uint16),
- ("Win32VersionValue", c_uint32),
- ("SizeOfImage", c_uint32),
- ("SizeOfHeaders", c_uint32),
- ("CheckSum", c_uint32),
- ("Subsystem", c_uint16),
- ("DllCharacteristics", c_uint16),
+ ("MajorImageVersion", c_uint16),
+ ("MinorImageVersion", c_uint16),
+ ("MajorSubsystemVersion", c_uint16),
+ ("MinorSubsystemVersion", c_uint16),
+ ("Win32VersionValue", c_uint32),
+ ("SizeOfImage", c_uint32),
+ ("SizeOfHeaders", c_uint32),
+ ("CheckSum", c_uint32),
+ ("Subsystem", c_uint16),
+ ("DllCharacteristics", c_uint16),
)
class PeOptionalHeaderEnd(LittleEndianStructure):
_fields_ = (
- ("LoaderFlags", c_uint32),
- ("NumberOfRvaAndSizes", c_uint32),
- ("ExportTable", PeDataDirectory),
- ("ImportTable", PeDataDirectory),
- ("ResourceTable", PeDataDirectory),
- ("ExceptionTable", PeDataDirectory),
- ("CertificateTable", PeDataDirectory),
- ("BaseRelocationTable", PeDataDirectory),
- ("Debug", PeDataDirectory),
- ("Architecture", PeDataDirectory),
- ("GlobalPtr", PeDataDirectory),
- ("TLSTable", PeDataDirectory),
- ("LoadConfigTable", PeDataDirectory),
- ("BoundImport", PeDataDirectory),
- ("IAT", PeDataDirectory),
+ ("LoaderFlags", c_uint32),
+ ("NumberOfRvaAndSizes", c_uint32),
+ ("ExportTable", PeDataDirectory),
+ ("ImportTable", PeDataDirectory),
+ ("ResourceTable", PeDataDirectory),
+ ("ExceptionTable", PeDataDirectory),
+ ("CertificateTable", PeDataDirectory),
+ ("BaseRelocationTable", PeDataDirectory),
+ ("Debug", PeDataDirectory),
+ ("Architecture", PeDataDirectory),
+ ("GlobalPtr", PeDataDirectory),
+ ("TLSTable", PeDataDirectory),
+ ("LoadConfigTable", PeDataDirectory),
+ ("BoundImport", PeDataDirectory),
+ ("IAT", PeDataDirectory),
("DelayImportDescriptor", PeDataDirectory),
- ("CLRRuntimeHeader", PeDataDirectory),
- ("Reserved", PeDataDirectory),
+ ("CLRRuntimeHeader", PeDataDirectory),
+ ("Reserved", PeDataDirectory),
)
@@ -152,44 +153,44 @@ class PeOptionalHeader(LittleEndianStructure):
class PeOptionalHeader32(PeOptionalHeader):
_anonymous_ = ("Start", "Middle", "End")
_fields_ = (
- ("Start", PeOptionalHeaderStart),
- ("BaseOfData", c_uint32),
- ("ImageBase", c_uint32),
- ("Middle", PeOptionalHeaderMiddle),
+ ("Start", PeOptionalHeaderStart),
+ ("BaseOfData", c_uint32),
+ ("ImageBase", c_uint32),
+ ("Middle", PeOptionalHeaderMiddle),
("SizeOfStackReserve", c_uint32),
- ("SizeOfStackCommit", c_uint32),
- ("SizeOfHeapReserve", c_uint32),
- ("SizeOfHeapCommit", c_uint32),
- ("End", PeOptionalHeaderEnd),
+ ("SizeOfStackCommit", c_uint32),
+ ("SizeOfHeapReserve", c_uint32),
+ ("SizeOfHeapCommit", c_uint32),
+ ("End", PeOptionalHeaderEnd),
)
class PeOptionalHeader32Plus(PeOptionalHeader):
_anonymous_ = ("Start", "Middle", "End")
_fields_ = (
- ("Start", PeOptionalHeaderStart),
- ("ImageBase", c_uint64),
- ("Middle", PeOptionalHeaderMiddle),
+ ("Start", PeOptionalHeaderStart),
+ ("ImageBase", c_uint64),
+ ("Middle", PeOptionalHeaderMiddle),
("SizeOfStackReserve", c_uint64),
- ("SizeOfStackCommit", c_uint64),
- ("SizeOfHeapReserve", c_uint64),
- ("SizeOfHeapCommit", c_uint64),
- ("End", PeOptionalHeaderEnd),
+ ("SizeOfStackCommit", c_uint64),
+ ("SizeOfHeapReserve", c_uint64),
+ ("SizeOfHeapCommit", c_uint64),
+ ("End", PeOptionalHeaderEnd),
)
class PeSection(LittleEndianStructure):
_fields_ = (
- ("Name", c_char * 8),
- ("VirtualSize", c_uint32),
- ("VirtualAddress", c_uint32),
- ("SizeOfRawData", c_uint32),
- ("PointerToRawData", c_uint32),
+ ("Name", c_char * 8),
+ ("VirtualSize", c_uint32),
+ ("VirtualAddress", c_uint32),
+ ("SizeOfRawData", c_uint32),
+ ("PointerToRawData", c_uint32),
("PointerToRelocations", c_uint32),
("PointerToLinenumbers", c_uint32),
- ("NumberOfRelocations", c_uint16),
- ("NumberOfLinenumbers", c_uint16),
- ("Characteristics", c_uint32),
+ ("NumberOfRelocations", c_uint16),
+ ("NumberOfLinenumbers", c_uint16),
+ ("Characteristics", c_uint32),
)
def __init__(self):
@@ -206,12 +207,13 @@ assert sizeof(PeOptionalHeader32Plus) == 240
PE_CHARACTERISTICS_RX = 0x60000020 # CNT_CODE|MEM_READ|MEM_EXECUTE
PE_CHARACTERISTICS_RW = 0xC0000040 # CNT_INITIALIZED_DATA|MEM_READ|MEM_WRITE
-PE_CHARACTERISTICS_R = 0x40000040 # CNT_INITIALIZED_DATA|MEM_READ
+PE_CHARACTERISTICS_R = 0x40000040 # CNT_INITIALIZED_DATA|MEM_READ
IGNORE_SECTIONS = [
".eh_frame",
".eh_frame_hdr",
".ARM.exidx",
+ ".relro_padding",
]
IGNORE_SECTION_TYPES = [
@@ -246,9 +248,12 @@ def align_down(x: int, align: int) -> int:
def next_section_address(sections: typing.List[PeSection]) -> int:
- return align_to(
- sections[-1].VirtualAddress + sections[-1].VirtualSize, SECTION_ALIGNMENT
- )
+ return align_to(sections[-1].VirtualAddress + sections[-1].VirtualSize,
+ SECTION_ALIGNMENT)
+
+
+class BadSectionError(ValueError):
+ "One of the sections is in a bad state"
def iter_copy_sections(elf: ELFFile) -> typing.Iterator[PeSection]:
@@ -261,8 +266,9 @@ def iter_copy_sections(elf: ELFFile) -> typing.Iterator[PeSection]:
relro = None
for elf_seg in elf.iter_segments():
if elf_seg["p_type"] == "PT_LOAD" and elf_seg["p_align"] != SECTION_ALIGNMENT:
- raise RuntimeError("ELF segments are not properly aligned.")
- elif elf_seg["p_type"] == "PT_GNU_RELRO":
+ raise BadSectionError(f"ELF segment {elf_seg['p_type']} is not properly aligned"
+ f" ({elf_seg['p_align']} != {SECTION_ALIGNMENT})")
+ if elf_seg["p_type"] == "PT_GNU_RELRO":
relro = elf_seg
for elf_s in elf.iter_sections():
@@ -270,10 +276,14 @@ def iter_copy_sections(elf: ELFFile) -> typing.Iterator[PeSection]:
elf_s["sh_flags"] & SH_FLAGS.SHF_ALLOC == 0
or elf_s["sh_type"] in IGNORE_SECTION_TYPES
or elf_s.name in IGNORE_SECTIONS
+ or elf_s["sh_size"] == 0
):
continue
if elf_s["sh_type"] not in ["SHT_PROGBITS", "SHT_NOBITS"]:
- raise RuntimeError(f"Unknown section {elf_s.name}.")
+ raise BadSectionError(f"Unknown section {elf_s.name} with type {elf_s['sh_type']}")
+ if elf_s.name == '.got':
+ # FIXME: figure out why those sections are inserted
+ print("WARNING: Non-empty .got section", file=sys.stderr)
if elf_s["sh_flags"] & SH_FLAGS.SHF_EXECINSTR:
rwx = PE_CHARACTERISTICS_RX
@@ -305,7 +315,7 @@ def iter_copy_sections(elf: ELFFile) -> typing.Iterator[PeSection]:
def convert_sections(elf: ELFFile, opt: PeOptionalHeader) -> typing.List[PeSection]:
- last_vma = 0
+ last_vma = (0, 0)
sections = []
for pe_s in iter_copy_sections(elf):
@@ -325,10 +335,11 @@ def convert_sections(elf: ELFFile, opt: PeOptionalHeader) -> typing.List[PeSecti
PE_CHARACTERISTICS_R: b".rodata",
}[pe_s.Characteristics]
- # This can happen if not building with `-z separate-code`.
- if pe_s.VirtualAddress < last_vma:
- raise RuntimeError("Overlapping PE sections.")
- last_vma = pe_s.VirtualAddress + pe_s.VirtualSize
+ # This can happen if not building with '-z separate-code'.
+ if pe_s.VirtualAddress < sum(last_vma):
+ raise BadSectionError(f"Section {pe_s.Name.decode()!r} @0x{pe_s.VirtualAddress:x} overlaps"
+ f" previous section @0x{last_vma[0]:x}+0x{last_vma[1]:x}=@0x{sum(last_vma):x}")
+ last_vma = (pe_s.VirtualAddress, pe_s.VirtualSize)
if pe_s.Name == b".text":
opt.BaseOfCode = pe_s.VirtualAddress
@@ -355,9 +366,9 @@ def copy_sections(
if not elf_s:
continue
if elf_s.data_alignment > 1 and SECTION_ALIGNMENT % elf_s.data_alignment != 0:
- raise RuntimeError(f"ELF section {name} is not aligned.")
+ raise BadSectionError(f"ELF section {name} is not aligned")
if elf_s["sh_flags"] & (SH_FLAGS.SHF_EXECINSTR | SH_FLAGS.SHF_WRITE) != 0:
- raise RuntimeError(f"ELF section {name} is not read-only data.")
+ raise BadSectionError(f"ELF section {name} is not read-only data")
pe_s = PeSection()
pe_s.Name = name.encode()
@@ -376,12 +387,8 @@ def apply_elf_relative_relocation(
sections: typing.List[PeSection],
addend_size: int,
):
- # fmt: off
- [target] = [
- pe_s for pe_s in sections
- if pe_s.VirtualAddress <= reloc["r_offset"] < pe_s.VirtualAddress + len(pe_s.data)
- ]
- # fmt: on
+ [target] = [pe_s for pe_s in sections
+ if pe_s.VirtualAddress <= reloc["r_offset"] < pe_s.VirtualAddress + len(pe_s.data)]
addend_offset = reloc["r_offset"] - target.VirtualAddress
@@ -425,9 +432,10 @@ def convert_elf_reloc_table(
continue
if reloc["r_info_type"] == RELATIVE_RELOC:
- apply_elf_relative_relocation(
- reloc, elf_image_base, sections, elf.elfclass // 8
- )
+ apply_elf_relative_relocation(reloc,
+ elf_image_base,
+ sections,
+ elf.elfclass // 8)
# Now that the ELF relocation has been applied, we can create a PE relocation.
block_rva = reloc["r_offset"] & ~0xFFF
@@ -442,7 +450,7 @@ def convert_elf_reloc_table(
continue
- raise RuntimeError(f"Unsupported relocation {reloc}")
+ raise BadSectionError(f"Unsupported relocation {reloc}")
def convert_elf_relocations(
@@ -453,27 +461,25 @@ def convert_elf_relocations(
) -> typing.Optional[PeSection]:
dynamic = elf.get_section_by_name(".dynamic")
if dynamic is None:
- raise RuntimeError("ELF .dynamic section is missing.")
+ raise BadSectionError("ELF .dynamic section is missing")
[flags_tag] = dynamic.iter_tags("DT_FLAGS_1")
if not flags_tag["d_val"] & ENUM_DT_FLAGS_1["DF_1_PIE"]:
- raise RuntimeError("ELF file is not a PIE.")
+ raise ValueError("ELF file is not a PIE")
# This checks that the ELF image base is 0.
symtab = elf.get_section_by_name(".symtab")
if symtab:
exe_start = symtab.get_symbol_by_name("__executable_start")
if exe_start and exe_start[0]["st_value"] != 0:
- raise RuntimeError("Unexpected ELF image base.")
-
- opt.SizeOfHeaders = align_to(
- PE_OFFSET
- + len(PE_MAGIC)
- + sizeof(PeCoffHeader)
- + sizeof(opt)
- + sizeof(PeSection) * max(len(sections) + 1, minimum_sections),
- FILE_ALIGNMENT,
- )
+ raise ValueError("Unexpected ELF image base")
+
+ opt.SizeOfHeaders = align_to(PE_OFFSET
+ + len(PE_MAGIC)
+ + sizeof(PeCoffHeader)
+ + sizeof(opt)
+ + sizeof(PeSection) * max(len(sections) + 1, minimum_sections),
+ FILE_ALIGNMENT)
# We use the basic VMA layout from the ELF image in the PE image. This could cause the first
# section to overlap the PE image headers during runtime at VMA 0. We can simply apply a fixed
@@ -482,9 +488,8 @@ def convert_elf_relocations(
# the ELF portions of the image.
segment_offset = 0
if sections[0].VirtualAddress < opt.SizeOfHeaders:
- segment_offset = align_to(
- opt.SizeOfHeaders - sections[0].VirtualAddress, SECTION_ALIGNMENT
- )
+ segment_offset = align_to(opt.SizeOfHeaders - sections[0].VirtualAddress,
+ SECTION_ALIGNMENT)
opt.AddressOfEntryPoint = elf["e_entry"] + segment_offset
opt.BaseOfCode += segment_offset
@@ -494,10 +499,12 @@ def convert_elf_relocations(
pe_reloc_blocks: typing.Dict[int, PeRelocationBlock] = {}
for reloc_type, reloc_table in dynamic.get_relocation_tables().items():
if reloc_type not in ["REL", "RELA"]:
- raise RuntimeError("Unsupported relocation type {elf_reloc_type}.")
- convert_elf_reloc_table(
- elf, reloc_table, opt.ImageBase + segment_offset, sections, pe_reloc_blocks
- )
+ raise BadSectionError(f"Unsupported relocation type {reloc_type}")
+ convert_elf_reloc_table(elf,
+ reloc_table,
+ opt.ImageBase + segment_offset,
+ sections,
+ pe_reloc_blocks)
for pe_s in sections:
pe_s.VirtualAddress += segment_offset
@@ -517,9 +524,7 @@ def convert_elf_relocations(
block.entries.append(PeRelocationEntry())
block.PageRVA += segment_offset
- block.BlockSize = (
- sizeof(PeRelocationBlock) + sizeof(PeRelocationEntry) * n_relocs
- )
+ block.BlockSize = sizeof(PeRelocationBlock) + sizeof(PeRelocationEntry) * n_relocs
data += block
for entry in sorted(block.entries, key=lambda e: e.Offset):
data += entry
@@ -539,7 +544,10 @@ def convert_elf_relocations(
def write_pe(
- file, coff: PeCoffHeader, opt: PeOptionalHeader, sections: typing.List[PeSection]
+ file,
+ coff: PeCoffHeader,
+ opt: PeOptionalHeader,
+ sections: typing.List[PeSection],
):
file.write(b"MZ")
file.seek(0x3C, io.SEEK_SET)
@@ -552,8 +560,8 @@ def write_pe(
offset = opt.SizeOfHeaders
for pe_s in sorted(sections, key=lambda s: s.VirtualAddress):
if pe_s.VirtualAddress < opt.SizeOfHeaders:
- # Linker script should make sure this does not happen.
- raise RuntimeError(f"Section {pe_s.Name} overlapping PE headers.")
+ raise BadSectionError(f"Section {pe_s.Name} @0x{pe_s.VirtualAddress:x} overlaps"
+ " PE headers ending at 0x{opt.SizeOfHeaders:x}")
pe_s.PointerToRawData = offset
file.write(pe_s)
@@ -571,9 +579,9 @@ def write_pe(
def elf2efi(args: argparse.Namespace):
elf = ELFFile(args.ELF)
if not elf.little_endian:
- raise RuntimeError("ELF file is not little-endian.")
+ raise ValueError("ELF file is not little-endian")
if elf["e_type"] not in ["ET_DYN", "ET_EXEC"]:
- raise RuntimeError("Unsupported ELF type.")
+ raise ValueError(f"Unsupported ELF type {elf['e_type']}")
pe_arch = {
"EM_386": 0x014C,
@@ -584,7 +592,7 @@ def elf2efi(args: argparse.Namespace):
"EM_X86_64": 0x8664,
}.get(elf["e_machine"])
if pe_arch is None:
- raise RuntimeError(f"Unsupported ELF arch {elf['e_machine']}")
+ raise ValueError(f"Unsupported ELF architecture {elf['e_machine']}")
coff = PeCoffHeader()
opt = PeOptionalHeader32() if elf.elfclass == 32 else PeOptionalHeader32Plus()
@@ -637,7 +645,7 @@ def elf2efi(args: argparse.Namespace):
write_pe(args.PE, coff, opt, sections)
-def main():
+def create_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Convert ELF binaries to PE/EFI")
parser.add_argument(
"--version-major",
@@ -691,7 +699,11 @@ def main():
default="",
help="Copy these sections if found",
)
+ return parser
+
+def main():
+ parser = create_parser()
elf2efi(parser.parse_args())
diff --git a/tools/git-contrib.sh b/tools/git-contrib.sh
index 6371d49..2cbcf6c 100755
--- a/tools/git-contrib.sh
+++ b/tools/git-contrib.sh
@@ -3,13 +3,7 @@
set -eu
tag="$(git describe --abbrev=0 --match 'v[0-9][0-9][0-9]')"
-(
- # authors
- git log --pretty=tformat:%aN -s "${tag}.."
- # Co-authors (drop empty line and mail addresses)
- git log --pretty='tformat:%(trailers:key=Co-authored-by,valueonly)' -s "${tag}.." | sed -e '/^[[:space:]]*$/ d' | sed -e 's/ <.*@.*>$//'
-) |
- grep -v noreply@weblate.org |
- sed 's/ / /g; s/--/-/g; s/.*/\0,/' |
- sort -u | tr '\n' ' ' | sed -e "s/^/Contributions from: /g" -e "s/,\s*$/\n/g" | fold -w 72 -s |
+git shortlog -s --group=author --group=trailer:Co-authored-by "${tag}.." |
+ sed -e 's/^[[:space:]]*[0-9]*[[:space:]]*//; /Weblate/ d; /dependabot\[bot\]/ d; s/ / /g; s/--/-/g; s/.*/\0,/' |
+ tr '\n' ' ' | sed -e "s/^/Contributions from: /g" -e "s/,\s*$/\n/g" | fold -w 72 -s |
sed -e "s/^/ /g" -e "s/\s*$//g"
diff --git a/tools/git-setup.sh b/tools/git-setup.sh
new file mode 100755
index 0000000..b5903b4
--- /dev/null
+++ b/tools/git-setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eu
+
+cd "${MESON_SOURCE_ROOT:?}"
+
+ret=2
+
+if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then
+ cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit
+ chmod +x .git/hooks/pre-commit
+ echo 'Activated pre-commit hook'
+ ret=0
+fi
+
+exit $ret
diff --git a/tools/make-man-index.py b/tools/make-man-index.py
index 579dd40..b4b262b 100755
--- a/tools/make-man-index.py
+++ b/tools/make-man-index.py
@@ -46,7 +46,7 @@ This index contains {count} entries, referring to {pages} individual manual page
def check_id(page, t):
page_id = t.getroot().get('id')
- if not re.search('/' + page_id + '[.]', page):
+ if not re.search('/' + page_id + '[.]', page.translate(str.maketrans('@', '_'))):
raise ValueError(f"id='{page_id}' is not the same as page name '{page}'")
def make_index(pages):
diff --git a/tools/meson-extract-unit-files.py b/tools/meson-extract-unit-files.py
new file mode 100755
index 0000000..f2b4fa3
--- /dev/null
+++ b/tools/meson-extract-unit-files.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import json
+import re
+import subprocess
+import sys
+
+def main():
+ build_dir = sys.argv[1]
+
+ out = subprocess.run(["meson", "introspect", "--installed", build_dir],
+ stdout=subprocess.PIPE, check=True)
+ files = json.loads(out.stdout)
+ for file in sorted(files.values()):
+ if re.search("^/usr/lib/systemd/(system|user)/", file) and not file.endswith(".conf"):
+ print(file)
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/meson-render-jinja2.py b/tools/meson-render-jinja2.py
index 3a3d912..977de79 100755
--- a/tools/meson-render-jinja2.py
+++ b/tools/meson-render-jinja2.py
@@ -33,12 +33,11 @@ def render(filename, defines):
def main():
defines = parse_config_h(sys.argv[1])
- defines.update(parse_config_h(sys.argv[2]))
- output = render(sys.argv[3], defines)
- with open(sys.argv[4], 'w') as f:
+ output = render(sys.argv[2], defines)
+ with open(sys.argv[3], 'w') as f:
f.write(output)
- info = os.stat(sys.argv[3])
- os.chmod(sys.argv[4], info.st_mode)
+ info = os.stat(sys.argv[2])
+ os.chmod(sys.argv[3], info.st_mode)
if __name__ == '__main__':
main()
diff --git a/tools/meson-vcs-tag.sh b/tools/meson-vcs-tag.sh
deleted file mode 100755
index 4a8dc89..0000000
--- a/tools/meson-vcs-tag.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-set -u
-set -o pipefail
-
-dir="${1:?}"
-fallback="${2:?}"
-version_tag="${3:-}"
-
-if [ -n "${version_tag}" ]; then
- # If -Dversion_tag= was used, just use that without further changes.
- echo "${version_tag}"
-else
- # Check that we have either .git/ (a normal clone) or a .git file (a work-tree)
- # and that we don't get confused if a tarball is extracted in a higher-level
- # git repository.
- #
- # If the working tree has no tags (CI builds), the first git-describe will fail
- # and we fall back to project_version-commitid instead.
-
- c=''
- if [ -e "${dir}/.git" ]; then
- c="$(git -C "$dir" describe --abbrev=7 --dirty=^ 2>/dev/null)"
- if [ -z "$c" ]; then
- # This call might still fail with permission issues
- suffix="$(git -C "$dir" describe --always --abbrev=7 --dirty=^ 2>/dev/null)"
- [ -n "$suffix" ] && c="${fallback}-${suffix}"
- fi
- fi
- [ -z "$c" ] && c="${fallback}"
- echo "$c" | sed 's/^v//; s/-rc/~rc/'
-fi
diff --git a/tools/update-dbus-docs.py b/tools/update-dbus-docs.py
index 008f7d4..ce7161c 100755
--- a/tools/update-dbus-docs.py
+++ b/tools/update-dbus-docs.py
@@ -152,12 +152,17 @@ def check_documented(document, declarations, stats, interface, missing_version):
stats['total'] += len(items)
for item in items:
- if klass == 'method':
+ if klass in ('method', 'signal'):
elem = 'function'
item_repr = f'{item}()'
- elif klass == 'signal':
- elem = 'function'
- item_repr = item
+
+ # Find all functions/signals in <function> elements that are not
+ # suffixed with '()' and fix them
+ for section in sections:
+ element = section.find(f".//{elem}[. = '{item}']")
+ if element is not None:
+ element.text = item_repr
+
elif klass == 'property':
elem = 'varname'
item_repr = item
@@ -259,7 +264,7 @@ def subst_output(document, programlisting, stats, missing_version):
variablelist = etree.Element("variablelist")
variablelist.attrib['class'] = 'dbus-'+decl_type
variablelist.attrib['generated'] = 'True'
- if decl_type == 'method' :
+ if decl_type in ('method', 'signal'):
variablelist.attrib['extra-ref'] = declaration + '()'
else:
variablelist.attrib['extra-ref'] = declaration
diff --git a/tools/update-distro-hash.py b/tools/update-distro-hash.py
new file mode 100755
index 0000000..16ed2e7
--- /dev/null
+++ b/tools/update-distro-hash.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+"""
+Fetch commits for pkg/{distribution} and, if changed, commit the latest hash.
+"""
+
+import argparse
+import json
+import shlex
+import subprocess
+from pathlib import Path
+
+def parse_args():
+ p = argparse.ArgumentParser(
+ description=__doc__,
+ )
+ p.add_argument(
+ 'distribution',
+ nargs='+',
+ )
+ p.add_argument(
+ '--no-fetch',
+ dest='fetch',
+ action='store_false',
+ default=True,
+ )
+ return p.parse_args()
+
+def read_config(distro: str):
+ cmd = ['mkosi', '--json', '-d', distro, 'summary']
+ print(f"+ {shlex.join(cmd)}")
+ text = subprocess.check_output(cmd, text=True)
+
+ data = json.loads(text)
+ return data['Images'][-1]
+
+def commit_file(distro: str, file: Path, commit: str, changes: str):
+ message = '\n'.join((
+ f'mkosi: update {distro} commit reference',
+ '',
+ changes))
+
+ cmd = ['git', 'commit', '-m', message, str(file)]
+ print(f"+ {shlex.join(cmd)}")
+ subprocess.check_call(cmd)
+
+def update_distro(args, distro: str):
+ cmd = ['git', '-C', f'pkg/{distro}', 'fetch']
+ print(f"+ {shlex.join(cmd)}")
+ subprocess.check_call(cmd)
+
+ config = read_config(distro)
+
+ branch = config['Environment']['GIT_BRANCH']
+ old_commit = config['Environment']['GIT_COMMIT']
+
+ cmd = ['git', '-C', f'pkg/{distro}', 'rev-parse', f'refs/remotes/origin/{branch}']
+ print(f"+ {shlex.join(cmd)}")
+ new_commit = subprocess.check_output(cmd, text=True).strip()
+
+ if old_commit == new_commit:
+ print(f'{distro}: commit {new_commit!s} is still fresh')
+ return
+
+ cmd = ['git', '-C', f'pkg/{distro}', 'log', '--graph',
+ '--pretty=oneline', '--no-decorate', '--abbrev-commit', '--abbrev=10',
+ f'{old_commit}..{new_commit}']
+ print(f"+ {shlex.join(cmd)}")
+ changes = subprocess.check_output(cmd, text=True).strip()
+
+ conf_dir = Path('mkosi.images/system/mkosi.conf.d')
+ files = conf_dir.glob('*/*.conf')
+ for file in files:
+ s = file.read_text()
+ if old_commit in s:
+ print(f'{distro}: {file}: found old hash, updating…')
+ new = s.replace(old_commit, new_commit)
+ assert new != s
+ file.write_text(new)
+ commit_file(distro, file, new_commit, changes)
+ break
+ else:
+ raise ValueError(f'{distro}: hash {new_commit} not found under {conf_dir}')
+
+if __name__ == '__main__':
+ args = parse_args()
+ for distro in args.distribution:
+ update_distro(args, distro)
diff --git a/tools/update-man-rules.py b/tools/update-man-rules.py
index 1c2c9a8..3f10a29 100755
--- a/tools/update-man-rules.py
+++ b/tools/update-man-rules.py
@@ -85,6 +85,7 @@ def main():
pages = glob.glob(source_glob)
pages = (p for p in pages
if Path(p).name not in {
+ 'standard-conf.xml',
'systemd.directives.xml',
'systemd.index.xml',
'directives-template.xml'})