Answers the question directly in docs/licensing.md §6, because "LDLS runs Linux drivers" reads like it contradicts §2 and does not. LDLS is Apache-2.0. Every file under ldls/ is ours; the loader came from the ELF-64 gABI and the x86-64 psABI. The licence of LDLS and the licence status of what happens at run time are two different questions and only the first is about us: ldls/ Apache-2.0 distributed by us a .ko GPL-2.0 distributed by the user's distro the two in one process -- distributed by nobody GPLv2 §0 says where its obligations attach -- "the act of running the Program is not restricted" -- so no combined work is distributed by anyone and no obligation is triggered. Same position FreeBSD has shipped from for a decade. Stated honestly in the same section: the *user* cannot redistribute the combination either, which is why RAMDISK_EXCLUDE exists and why .gitignore refuses *.ko. EXPORT_SYMBOL_GPL was left open in the plan; it is now answered and the answer is cleaner than expected. That marking gates *Linux's own* symbols. Every symbol LDLS provides is ours, reimplemented from facts, so there is no gate being bypassed because no Linux symbol is being exposed. LDLS implements no licence check -- it reads the declared licence and prints it before loading anything. And the sharpest edge in rule 3 mostly goes away. The uncomfortable row was struct layouts, which a compiled driver indexes by offset, so the shim must reproduce them exactly -- and a field-for-field match looks like transcription even when it is not. It does not have to be in our source: kernels built with CONFIG_DEBUG_INFO_BTF publish /sys/kernel/btf/vmlinux, and that carries both the layouts and the function prototypes as generated type data about the kernel the user already has. Verified on this machine: struct pci_dev field by field, and FUNC 'pci_iomap' with its FUNC_PROTO. LDLS reads them at load time on the user's machine; our source contains neither. That also mostly dissolves rule 4, since BTF describes the kernel that is actually installed rather than one pinned by guessing. What BTF does not give is behaviour -- what napi_complete_done *does* is still ours to write from documentation, and that is the whole of the real work. Also adds the SPDX header ldls/ko.h was missing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
213 lines
7.7 KiB
C
213 lines
7.7 KiB
C
// SPDX-License-Identifier: Apache-2.0
|
|
#pragma once
|
|
|
|
// Loading a relocatable object. docs/plan/ldls.md milestone L0.
|
|
//
|
|
// A Linux `.ko` is an ordinary ELF64 relocatable object -- the same thing
|
|
// `gcc -c` produces -- and loading one is four steps with no mystery in any of
|
|
// them: index the sections, place the allocatable ones, resolve the undefined
|
|
// symbols against a table, and apply the relocations. There is no licence
|
|
// question anywhere in this file: ELF and the x86-64 relocation set are
|
|
// published specifications, which is the case [../docs/licensing.md] §5
|
|
// describes.
|
|
//
|
|
// **It is freestanding on purpose.** No libc, no allocation, no I/O: the
|
|
// caller hands over the whole image and a buffer, and everything happens in
|
|
// them. That is what lets the same source build as a host tool -- where a test
|
|
// takes a second -- and as the SchOS-side host, which is the discipline
|
|
// `mkschfs` and the kernel already share and the reason SchFS format bugs are
|
|
// found on the host.
|
|
//
|
|
// Types are spelled out rather than taken from a header, because the two sides
|
|
// have different ones and this file has to mean the same thing in both.
|
|
|
|
// The section table is the caller's, not ours.
|
|
//
|
|
// A fixed array needs a limit, and every limit that would fit in a struct is
|
|
// one a real object exceeds: measured over 300 modules the median is 50
|
|
// sections and the 95th percentile is 67, but an object built with
|
|
// -ffunction-sections runs to thousands -- nvidia-modeset has 7,069. Rather
|
|
// than pick a number that is generous until it is not, the caller says how
|
|
// many it is prepared for, and ko_sections_needed() says how many that is.
|
|
//
|
|
// A suggested size for a fixed table on the SchOS side, where allocating is
|
|
// less convenient. It is a caller's choice and not the loader's limit.
|
|
#define KO_SECHINT 128
|
|
|
|
// Undefined symbols the report will hold. Measured over the same corpus the
|
|
// median is 25 and the worst seen is 245, so this is room to spare -- and
|
|
// `undef_lost` says so rather than the list quietly ending.
|
|
#define KO_MAXUNDEF 512
|
|
|
|
// --- ELF64, the relocatable subset ------------------------------------------
|
|
//
|
|
// include/elf.h has `elfhdr` and `proghdr`, which are the ET_EXEC half. None of
|
|
// what a relocatable object needs is there, so it is here.
|
|
|
|
struct ko_ehdr {
|
|
unsigned char e_ident[16];
|
|
unsigned short e_type;
|
|
unsigned short e_machine;
|
|
unsigned int e_version;
|
|
unsigned long long e_entry;
|
|
unsigned long long e_phoff;
|
|
unsigned long long e_shoff;
|
|
unsigned int e_flags;
|
|
unsigned short e_ehsize;
|
|
unsigned short e_phentsize;
|
|
unsigned short e_phnum;
|
|
unsigned short e_shentsize;
|
|
unsigned short e_shnum;
|
|
unsigned short e_shstrndx;
|
|
};
|
|
|
|
struct ko_shdr {
|
|
unsigned int sh_name;
|
|
unsigned int sh_type;
|
|
unsigned long long sh_flags;
|
|
unsigned long long sh_addr;
|
|
unsigned long long sh_offset;
|
|
unsigned long long sh_size;
|
|
unsigned int sh_link;
|
|
unsigned int sh_info;
|
|
unsigned long long sh_addralign;
|
|
unsigned long long sh_entsize;
|
|
};
|
|
|
|
struct ko_sym {
|
|
unsigned int st_name;
|
|
unsigned char st_info;
|
|
unsigned char st_other;
|
|
unsigned short st_shndx;
|
|
unsigned long long st_value;
|
|
unsigned long long st_size;
|
|
};
|
|
|
|
struct ko_rela {
|
|
unsigned long long r_offset;
|
|
unsigned long long r_info;
|
|
long long r_addend;
|
|
};
|
|
|
|
#define KO_ET_REL 1
|
|
#define KO_EM_X86_64 62
|
|
|
|
#define KO_SHT_PROGBITS 1
|
|
#define KO_SHT_SYMTAB 2
|
|
#define KO_SHT_STRTAB 3
|
|
#define KO_SHT_RELA 4
|
|
#define KO_SHT_NOBITS 8
|
|
|
|
#define KO_SHF_WRITE 0x1
|
|
#define KO_SHF_ALLOC 0x2
|
|
#define KO_SHF_EXECINSTR 0x4
|
|
|
|
#define KO_SHN_UNDEF 0
|
|
#define KO_SHN_ABS 0xfff1
|
|
#define KO_SHN_COMMON 0xfff2
|
|
|
|
#define KO_R_SYM(i) ((unsigned int)((i) >> 32))
|
|
#define KO_R_TYPE(i) ((unsigned int)((i) & 0xffffffffu))
|
|
|
|
// The x86-64 relocations a compiled object actually contains. Anything else is
|
|
// refused by name rather than ignored -- a relocation silently skipped is a
|
|
// wrong address found much later.
|
|
#define KO_R_X86_64_NONE 0
|
|
#define KO_R_X86_64_64 1
|
|
#define KO_R_X86_64_PC32 2
|
|
#define KO_R_X86_64_PLT32 4
|
|
#define KO_R_X86_64_32 10
|
|
#define KO_R_X86_64_32S 11
|
|
#define KO_R_X86_64_PC64 24
|
|
|
|
// --- what the loader knows about a section ----------------------------------
|
|
|
|
struct ko_section {
|
|
const char *name;
|
|
unsigned int type;
|
|
unsigned long long flags;
|
|
unsigned long long size;
|
|
unsigned long long align;
|
|
const unsigned char *data; // 0 for NOBITS
|
|
int alloc; // takes space at run time
|
|
unsigned long long addr; // where it will run, once laid out
|
|
unsigned char *where; // where it is right now, once laid out
|
|
};
|
|
|
|
// Resolving a name to an address. Returns 0 and fills `out` on success, or
|
|
// non-zero to say it does not know it -- which is not an error at L0, it is
|
|
// the answer we are asking for.
|
|
typedef int (*ko_resolver)(void *ctx, const char *name,
|
|
unsigned long long *out);
|
|
|
|
struct ko {
|
|
const unsigned char *img;
|
|
unsigned long long len;
|
|
|
|
const struct ko_ehdr *eh;
|
|
const unsigned char *shtab; // raw, indexed with e_shentsize
|
|
int nsh;
|
|
|
|
const char *shstr; // section name strings
|
|
const struct ko_sym *sym;
|
|
int nsym;
|
|
const char *str; // symbol name strings
|
|
|
|
struct ko_section *sec; // the caller's, nsh entries used
|
|
|
|
const char *undef[KO_MAXUNDEF];
|
|
int nundef;
|
|
int undef_lost; // more than KO_MAXUNDEF of them
|
|
|
|
unsigned long long span; // bytes ko_layout needs
|
|
int laid_out;
|
|
|
|
// How many relocations of each type the object contains, counted by
|
|
// ko_reltypes(). The question "what does the loader actually have to
|
|
// handle" has an exact answer per module, and guessing at it is how a
|
|
// loader ends up refusing a driver on its last relocation.
|
|
unsigned int reltype[64];
|
|
unsigned int reltype_other;
|
|
unsigned int nrel;
|
|
|
|
char err[128];
|
|
};
|
|
|
|
// How many `struct ko_section` this object needs. -1 if it is not an ELF64
|
|
// object at all, which is worth knowing before allocating anything for it.
|
|
int ko_sections_needed(const void *image, unsigned long long len);
|
|
|
|
// Validate and index, using `sec` for the section table. Returns 0, or -1 with
|
|
// ko_err() set -- including when `nsec` is too small, which says how many were
|
|
// needed rather than just refusing.
|
|
int ko_open(struct ko *k, const void *image, unsigned long long len,
|
|
struct ko_section *sec, int nsec);
|
|
|
|
// Bytes ko_layout will need. Valid after ko_open.
|
|
unsigned long long ko_span(const struct ko *k);
|
|
|
|
// Place every allocatable section into `mem`, as if it will run at `base`.
|
|
// The two differ when the object is staged somewhere before being mapped;
|
|
// pass base == (address of mem) when they do not.
|
|
int ko_layout(struct ko *k, void *mem, unsigned long long cap,
|
|
unsigned long long base);
|
|
|
|
// Count the relocations by type, without applying any. Valid after ko_open.
|
|
void ko_reltypes(struct ko *k);
|
|
|
|
// Apply every relocation. Undefined symbols go to `r`; a name it does not know
|
|
// makes this fail, naming the first one.
|
|
int ko_relocate(struct ko *k, ko_resolver r, void *ctx);
|
|
|
|
// A value from the `.modinfo` section -- "license", "description", "author",
|
|
// "alias". Returns 0 if the object has no such key.
|
|
//
|
|
// Worth having at L0 rather than later: the first thing anyone should be able
|
|
// to ask about a module is what licence it declares, and that is a string in
|
|
// the file rather than anything that needs loading.
|
|
const char *ko_modinfo(const struct ko *k, const char *key);
|
|
|
|
// The module's own name, from `.gnu.linkonce.this_module`, or 0.
|
|
const char *ko_name(const struct ko *k);
|
|
|
|
const char *ko_err(const struct ko *k);
|