Unverified Commit 610f4415 authored by PhoeniX's avatar PhoeniX

Smart self-deleting pointers

parent 6365427f
Pipeline #1852 passed with stages
in 33 seconds
......@@ -20,3 +20,25 @@ class Heap {
static void free(void* addr);
};
template<typename T> class ptr {
private:
T *value;
public:
ptr() : value(nullptr) {}
explicit ptr(T *value) : value(value) {}
~ptr() { delete value; }
inline void reset(T* newvalue) { delete value; value = newvalue; }
inline void operator=(T* newvalue) { reset(newvalue); }
inline operator bool() const { return value != nullptr; }
inline T& operator*() { return *value; }
inline T* operator->() { return value; }
inline T* get() { return value; }
inline T& operator[](ptrdiff_t idx) { return value[idx]; }
inline const T& operator*() const { return *value; }
inline const T* operator->() const { return value; }
inline const T* get() const { return value; }
inline const T& operator[](ptrdiff_t idx) const { return value[idx]; }
};
......@@ -10,9 +10,8 @@
static void syscall_puts(uintptr_t strptr) {
Process *process = ProcessManager::getManager()->currentProcess();
const char *str = process->readString(strptr);
Display::getInstance()->write(str);
delete str;
ptr<char> str(process->readString(strptr));
Display::getInstance()->write(str.get());
}
static void syscall_exit(int code) {
......@@ -37,11 +36,10 @@ static void syscall_kread(void *out, const void *kaddr, size_t size) {
process->writeData(uintptr_t(out), kaddr, size);
}
static void syscall_ioprovide(const char *path, const void *ptr) {
static void syscall_ioprovide(const char *path, const void *modptr) {
Process *process = ProcessManager::getManager()->currentProcess();
char *str = process->readString(uintptr_t(path));
printf("ioprovide [%s(%#lx) / %p] [%s]\n", process->getName(), process->getId(), ptr, str);
delete str;
ptr<char> str(process->readString(uintptr_t(path)));
printf("ioprovide [%s(%#lx) / %p] [%s]\n", process->getName(), process->getId(), modptr, str.get());
}
#define SYSCALL_ENT(name) { \
......
......@@ -9,7 +9,7 @@
class ModuleManager {
private:
struct ModuleInfo {
char *name, *version, *description, *requirements, *developer;
ptr<char> name, version, description, requirements, developer;
};
static Mutex managerMutex;
static volatile ModuleManager* manager;
......
......@@ -10,6 +10,12 @@ volatile ModuleManager* ModuleManager::manager = nullptr;
Mutex ModuleManager::managerMutex;
bool ModuleManager::parseModuleInfo(ModuleInfo *info, const Process *process) {
info->name = nullptr;
info->version = nullptr;
info->description = nullptr;
info->requirements = nullptr;
info->developer = nullptr;
struct {
uintptr_t name, version, desc, reqs, dev;
} symbols = {
......@@ -19,19 +25,16 @@ bool ModuleManager::parseModuleInfo(ModuleInfo *info, const Process *process) {
process->getSymbolByName("module_requirements"),
process->getSymbolByName("module_developer")
};
ModuleInfo mod = { nullptr, nullptr, nullptr, nullptr, nullptr };
if ((symbols.name == 0) || (symbols.version == 0)
|| (symbols.desc == 0) || (symbols.reqs == 0) || (symbols.dev == 0))
return false;
mod.name = process->readString(symbols.name);
mod.version = process->readString(symbols.version);
mod.description = process->readString(symbols.desc);
mod.requirements = process->readString(symbols.reqs);
mod.developer = process->readString(symbols.dev);
*info = mod;
info->name = process->readString(symbols.name);
info->version = process->readString(symbols.version);
info->description = process->readString(symbols.desc);
info->requirements = process->readString(symbols.reqs);
info->developer = process->readString(symbols.dev);
return true;
}
......@@ -127,24 +130,18 @@ void ModuleManager::loadStream(Stream *stream) {
size_t size;
ModuleInfo mod;
for (;;) {
mod = {nullptr, nullptr, nullptr, nullptr, nullptr};
process = new Process();
size = readelf(process, sub);
if (size == 0 || !parseModuleInfo(&mod, process)) {
delete process;
break;
}
process->setName(mod.name);
if (bindRequirements(mod.requirements, process)) {
process->setName(mod.name.get());
if (bindRequirements(mod.requirements.get(), process)) {
process->startup();
} else {
delete process;
}
delete mod.name;
delete mod.version;
delete mod.description;
delete mod.requirements;
delete mod.developer;
sub->seek(ptrdiff_t(size), -1);
if (!stream->eof()) {
......@@ -153,8 +150,7 @@ void ModuleManager::loadStream(Stream *stream) {
sub = _sub;
}
}
if (sub != stream)
delete sub;
if (sub != stream) delete sub;
}
void ModuleManager::parseInternal() {
const char *mods_start, *mods_end;
......
......@@ -106,19 +106,17 @@ static bool readelf_dylink_process_reloc(Process *process, uintptr_t start, cons
if (!sym.name) return 0;
uintptr_t addr = 0;
char *name = process->readString(strtab + sym.name);
ptr<char> name(process->readString(strtab + sym.name));
uintptr_t ptr = readelf_find_load_addr(process, start, ent.addr);
bool allownull = sym.bind == ELF64::SYM::STB_WEAK;
addr = process->getSymbolByName(name);
if (!addr) addr = process->linkLibrary(name);
addr = process->getSymbolByName(name.get());
if (!addr) addr = process->linkLibrary(name.get());
if (!allownull && addr == 0) {
printf("Cannot link symbol: %s\n", name);
delete name;
printf("Cannot link symbol: %s\n", name.get());
return 0;
}
delete name;
addr += ent.add;
switch (ent.type) {
......@@ -209,6 +207,7 @@ static bool readelf_dylink_handle_dynamic_symtab(Process *process, uintptr_t sta
} PACKED hashhdr;
process->readData(&hashhdr, hashtab, sizeof(hashhdr));
hashtab += sizeof(hashhdr);
ptr<char> name;
for (uint32_t si = 0; si < hashhdr.nbucket + hashhdr.nchain; si++) {
uint32_t idx;
process->readData(&idx, hashtab, sizeof(idx));
......@@ -218,9 +217,8 @@ static bool readelf_dylink_handle_dynamic_symtab(Process *process, uintptr_t sta
if (sym.name == 0) continue;
uintptr_t ptr = readelf_find_load_addr(process, start, sym.value);
if (ptr == 0) continue;
char *name = process->readString(strtab + sym.name);
if (name && name[0] != 0) process->addSymbol(name, ptr);
delete name;
name = process->readString(strtab + sym.name);
if (name && name[0] != 0) process->addSymbol(name.get(), ptr);
}
return 1;
}
......@@ -296,14 +294,15 @@ static bool readelf_dylink(Process *process, uintptr_t start) {
size_t readelf(Process *process, Stream *stream) {
ELF::HDR elf;
size_t size = 0;
ELF64::PROG *progs = nullptr, *progs_top, *prog;
char *buf = nullptr;
ELF64::PROG *progs_top, *prog;
ptr<ELF64::PROG> progs;
ptr<char> buf;
SectionType type;
uintptr_t vaddr, offset_load, vaddr_start = 0;
// Read ELF header
size_t off = 0;
if (stream->read(&elf, sizeof(ELF::HDR)) != sizeof(ELF::HDR)) goto err;
if (stream->read(&elf, sizeof(ELF::HDR)) != sizeof(ELF::HDR)) return 0;
off += sizeof(ELF::HDR);
// Identify ELF
......@@ -312,35 +311,33 @@ size_t readelf(Process *process, Stream *stream) {
|| (elf.ident.data != ELF::ED_2LSB)
|| (elf.ident.version != ELF::EVF_CURRENT)
|| (elf.ident.osabi != 0)
|| (elf.ident.abiversion != 0)) goto err;
|| (elf.ident.abiversion != 0)) return 0;
// Check ELF type
if ((elf.machine != ELF::EM_AMD64)
|| (elf.type != ELF::ET_DYN)
|| (elf.version != ELF::EV_CURRENT)
|| (elf.flags != 0)
|| (elf.ehsize != sizeof(ELF::HDR))
|| (elf.phoff != sizeof(ELF::HDR))) goto err;
|| (elf.phoff != sizeof(ELF::HDR))) return 0;
// Init variables
size = elf.shoff + elf.shentsize * elf.shnum;
progs = new ELF64::PROG[elf.phnum]();
progs_top = progs + elf.phnum;
progs_top = progs.get() + elf.phnum;
// Read linker program
if (stream->read(progs, sizeof(ELF64::PROG) * elf.phnum) != sizeof(ELF64::PROG) * elf.phnum)
goto err;
if (stream->read(progs.get(), sizeof(ELF64::PROG) * elf.phnum) != sizeof(ELF64::PROG) * elf.phnum) return 0;
off += sizeof(ELF64::PROG) * elf.phnum;
for (prog = progs; prog < progs_top; prog++) {
for (prog = progs.get(); prog < progs_top; prog++) {
switch (prog->type) {
case ELF64::PROG::PT_NULL: break;
case ELF64::PROG::PT_PHDR:
if ((prog->offset != elf.phoff) || (prog->filesz != sizeof(ELF64::PROG) * elf.phnum))
goto err;
if ((prog->offset != elf.phoff) || (prog->filesz != sizeof(ELF64::PROG) * elf.phnum)) return 0;
break;
case ELF64::PROG::PT_LOAD:
if (prog->flags & ELF64::PROG::PF_X) {
if (prog->flags & ELF64::PROG::PF_W) goto err;
if (prog->flags & ELF64::PROG::PF_W) return 0;
type = SectionTypeCode;
} else {
if (prog->flags & ELF64::PROG::PF_W)
......@@ -356,16 +353,15 @@ size_t readelf(Process *process, Stream *stream) {
process->writeData(vaddr, &elf, sizeof(ELF::HDR));
offset_load = sizeof(ELF::HDR) + sizeof(ELF64::PROG) * elf.phnum;
}
if (prog->offset + offset_load < off) goto err;
if (prog->offset + offset_load < off) return 0;
if (prog->offset + offset_load > off) {
stream->seek(ptrdiff_t(prog->offset + offset_load - off), 0);
off = prog->offset + offset_load;
}
buf = new char[prog->filesz - offset_load]();
if (stream->read(buf, prog->filesz - offset_load) != prog->filesz - offset_load) goto err;
if (stream->read(buf.get(), prog->filesz - offset_load) != prog->filesz - offset_load) return 0;
off += prog->filesz - offset_load;
process->writeData(vaddr + offset_load, buf, prog->filesz - offset_load);
delete[] buf; buf = nullptr;
process->writeData(vaddr + offset_load, buf.get(), prog->filesz - offset_load);
prog->vaddr = vaddr;
}
break;
......@@ -373,20 +369,12 @@ size_t readelf(Process *process, Stream *stream) {
default:
if (prog->type >= ELF64::PROG::PT_LOOS && prog->type <= ELF64::PROG::PT_HIOS) break;
if (prog->type >= ELF64::PROG::PT_LOPROC && prog->type <= ELF64::PROG::PT_HIPROC) break;
goto err;
return 0;
}
}
process->writeData(vaddr_start + sizeof(ELF::HDR), progs, sizeof(ELF64::PROG) * elf.phnum);
process->writeData(vaddr_start + sizeof(ELF::HDR), progs.get(), sizeof(ELF64::PROG) * elf.phnum);
goto done;
err:
size = 0;
done:
delete progs;
delete buf;
if (size != 0) {
if (!readelf_dylink(process, vaddr_start)) size = 0;
}
if (!readelf_dylink(process, vaddr_start)) return 0;
return size;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment