elf.c: section limit inference for linux, fixes for stb_ds.h hashing, more compilation flags
This commit is contained in:
@ -244,7 +244,7 @@ static void audio_sample_and_mixin_channel(const struct audio_channel *channel,
|
||||
static uint8_t buffer[16384];
|
||||
const int int16_buffer_frames = sizeof (buffer) / sizeof (int16_t);
|
||||
const int float_buffer_frames = sizeof (buffer) / sizeof (float);
|
||||
const int stream_frames = len / sizeof (int16_t);
|
||||
const int stream_frames = len / (int)(sizeof (int16_t));
|
||||
|
||||
switch (channel->file_type) {
|
||||
case audio_file_type_ogg: {
|
||||
|
@ -65,6 +65,7 @@ static void ingame_end(struct state *state) {
|
||||
struct scene_ingame *scn = (struct scene_ingame *)state->scene;
|
||||
player_destroy(scn->player);
|
||||
world_destroy(scn->world);
|
||||
free(state->scene);
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,6 +24,7 @@ static void title_end(struct state *state) {
|
||||
struct scene_title *scn = (struct scene_title *)state->scene;
|
||||
player_destroy(scn->player);
|
||||
world_destroy(scn->world);
|
||||
free(state->scene);
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +95,6 @@ union uncolored_space_triangle {
|
||||
/* batch of primitives with overlapping properties */
|
||||
struct mesh_batch {
|
||||
GLuint buffer; /* server side storage */
|
||||
size_t buffer_len; /* element count */
|
||||
uint8_t *primitives;
|
||||
};
|
||||
|
||||
|
68
src/system/linux/elf.c
Normal file
68
src/system/linux/elf.c
Normal file
@ -0,0 +1,68 @@
|
||||
#include "elf.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <elf.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
bool infer_elf_section_bounds(const char *const restrict name,
|
||||
const char **restrict vm_start,
|
||||
const char **restrict vm_end)
|
||||
{
|
||||
bool result = false;
|
||||
char buf[PATH_MAX];
|
||||
ssize_t l = readlink("/proc/self/exe", buf, PATH_MAX);
|
||||
if (l == -1)
|
||||
goto ERR_CANT_READLINK;
|
||||
buf[l] = 0; /* readlink() doesn't write a terminator */
|
||||
|
||||
int elf = open(buf, O_RDONLY);
|
||||
if (elf == -1)
|
||||
goto ERR_CANT_OPEN_SELF;
|
||||
|
||||
/* elf header */
|
||||
Elf64_Ehdr ehdr;
|
||||
read(elf, &ehdr, sizeof ehdr);
|
||||
if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
|
||||
ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
|
||||
ehdr.e_ident[EI_MAG3] != ELFMAG3)
|
||||
goto ERR_NOT_ELF;
|
||||
|
||||
/* section header string table */
|
||||
Elf64_Shdr shstrdr;
|
||||
lseek(elf, ehdr.e_shoff + ehdr.e_shstrndx * sizeof (Elf64_Shdr), SEEK_SET);
|
||||
read(elf, &shstrdr, sizeof shstrdr);
|
||||
char *sh = malloc(shstrdr.sh_size);
|
||||
lseek(elf, shstrdr.sh_offset, SEEK_SET);
|
||||
read(elf, sh, shstrdr.sh_size);
|
||||
|
||||
/* walk sections searching for needed name */
|
||||
lseek(elf, ehdr.e_shoff, SEEK_SET);
|
||||
for (size_t s = 0; s < ehdr.e_shnum; ++s) {
|
||||
Elf64_Shdr shdr;
|
||||
read(elf, &shdr, sizeof shdr);
|
||||
|
||||
if (strcmp(&sh[shdr.sh_name], name) == 0) {
|
||||
result = true;
|
||||
*vm_start = getauxval(AT_ENTRY) - ehdr.e_entry + (char *)shdr.sh_addr;
|
||||
*vm_end = getauxval(AT_ENTRY) - ehdr.e_entry + (char *)shdr.sh_addr + shdr.sh_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(sh);
|
||||
|
||||
ERR_NOT_ELF:
|
||||
close(elf);
|
||||
|
||||
ERR_CANT_OPEN_SELF:
|
||||
ERR_CANT_READLINK:
|
||||
return result;
|
||||
}
|
10
src/system/linux/elf.h
Normal file
10
src/system/linux/elf.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef ELF_H
|
||||
#define ELF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool infer_elf_section_bounds(const char *restrict name,
|
||||
const char **restrict vm_start,
|
||||
const char **restrict vm_end);
|
||||
|
||||
#endif
|
@ -295,8 +295,9 @@ void textures_dump_atlases(struct texture_cache *cache) {
|
||||
|
||||
static t_texture_key textures_load(struct texture_cache *cache, const char *path) {
|
||||
/* no need to do anything if it was loaded already */
|
||||
if (shgeti(cache->hash, path) >= 0)
|
||||
return (t_texture_key){0};
|
||||
const ptrdiff_t i = shgeti(cache->hash, path);
|
||||
if (i >= 0)
|
||||
return (t_texture_key){ (uint16_t)i };
|
||||
|
||||
SDL_Surface *surface = image_to_surface(path);
|
||||
struct texture new_texture = {0};
|
||||
@ -308,12 +309,12 @@ static t_texture_key textures_load(struct texture_cache *cache, const char *path
|
||||
upload_texture_from_surface(new_texture.loner_texture, surface);
|
||||
new_texture.srcrect = (t_rect) { .w = surface->w, .h = surface->h };
|
||||
shput(cache->hash, path, new_texture);
|
||||
return (t_texture_key){ shgeti(cache->hash, path) };
|
||||
return (t_texture_key){ (uint16_t)shgeti(cache->hash, path) };
|
||||
} else {
|
||||
new_texture.atlas_index = cache->atlas_index;
|
||||
shput(cache->hash, path, new_texture);
|
||||
cache->is_dirty = true;
|
||||
return (t_texture_key){ shgeti(cache->hash, path) };
|
||||
return (t_texture_key){ (uint16_t)shgeti(cache->hash, path) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,35 +364,44 @@ void textures_update_atlas(struct texture_cache *cache) {
|
||||
}
|
||||
|
||||
/* EXPERIMANTAL: LIKELY TO BE REMOVED! */
|
||||
/* todo: If it's proven to be useful: add runtime checking for .rodata > .data */
|
||||
#ifdef __unix__ /* use rodata elf section for fast lookups of repeating textures */
|
||||
#ifdef __linux__ /* use rodata elf section for fast lookups of repeating textures */
|
||||
|
||||
extern const char start_rodata_address[];
|
||||
extern const char stop_rodata_heuristic[];
|
||||
#include "system/linux/elf.h"
|
||||
|
||||
asm(".set start_rodata_address, .rodata");
|
||||
asm(".set stop_rodata_heuristic, .data"); /* there's nothing in default linker script to know the size of .rodata */
|
||||
static const char *rodata_start;
|
||||
static const char *rodata_stop;
|
||||
|
||||
/* TODO: it might be better to contruct a new table that hashes pointers, not strings, to texture keys */
|
||||
/* this way every used texture will benefit, no matter the order of commission */
|
||||
t_texture_key textures_get_key(struct texture_cache *cache, const char *path) {
|
||||
static const char *last_path = NULL;
|
||||
static t_texture_key last_texture;
|
||||
static struct ptr_to_texture {
|
||||
const void *key;
|
||||
t_texture_key value;
|
||||
} *ptr_to_texture;
|
||||
|
||||
/* fast path */
|
||||
if (rodata_stop == NULL)
|
||||
if (!infer_elf_section_bounds(".rodata", &rodata_start, &rodata_stop))
|
||||
CRY("Section inference", ".rodata section lookup failed");
|
||||
|
||||
/* the fastest path */
|
||||
if (path == last_path)
|
||||
return last_texture;
|
||||
else {
|
||||
/* moderately fast path, by pointer hashing */
|
||||
const ptrdiff_t texture = hmgeti(ptr_to_texture, path);
|
||||
if (texture != -1) {
|
||||
if (path >= rodata_start && path < rodata_stop)
|
||||
last_path = path;
|
||||
last_texture = ptr_to_texture[texture].value;
|
||||
return last_texture;
|
||||
}
|
||||
}
|
||||
|
||||
/* hash tables are assumed to be stable, so we just return indices */
|
||||
ptrdiff_t texture = shgeti(cache->hash, path);
|
||||
/* try loading */
|
||||
last_texture = textures_load(cache, path);
|
||||
hmput(ptr_to_texture, path, last_texture);
|
||||
|
||||
/* load it if it isn't */
|
||||
if (texture == -1) {
|
||||
last_texture = textures_load(cache, path);
|
||||
} else
|
||||
last_texture = (t_texture_key){ (uint16_t)texture };
|
||||
|
||||
if (path >= start_rodata_address && path < stop_rodata_heuristic)
|
||||
if (path >= rodata_start && path < rodata_stop)
|
||||
last_path = path;
|
||||
|
||||
return last_texture;
|
||||
@ -400,7 +410,7 @@ t_texture_key textures_get_key(struct texture_cache *cache, const char *path) {
|
||||
#else
|
||||
t_texture_key textures_get_key(struct texture_cache *cache, const char *path) {
|
||||
/* hash tables are assumed to be stable, so we just return indices */
|
||||
ptrdiff_t texture = shgeti(cache->hash, path);
|
||||
const ptrdiff_t texture = shgeti(cache->hash, path);
|
||||
|
||||
/* load it if it isn't */
|
||||
if (texture == -1) {
|
||||
|
Reference in New Issue
Block a user