Instrumented map.c functions with TRACE()s

Added `map_handle_err()` for easier error reporting and handling

Added `map_error_str()` to convert a non-`MAP_SUCCESS` `map_result_t` into an error message

Fortune for naka's current commit: Small blessing − 小吉
master
Avril 3 years ago
parent f8f5d9102e
commit f3538aa2db
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -13,6 +13,7 @@ typedef enum mm_err {
MAP_ERR_UNMAP,
MAP_ERR_OPEN,
MAP_ERR_CLOSE,
MAP_ERR_STAT,
} map_result_t;
typedef union memory_map {
@ -41,4 +42,27 @@ map_result_t map_file(const char* file, bool write, usize size, off_t offset, ma
map_result_t map_anon(void* ptr, usize len, map_t *pOUT map);
map_result_t map_free(map_t map);
const char* map_error_str(map_result_t res);
_mixin int _map_handle_err(const char* stmt, const char* file, int line, const char* func, map_result_t res)
{
if(res == MAP_SUCCESS) return 1;
else {
const char* err = map_error_str(res);
ERROR("mapping failed at %s:%d->%s(): on stmt `%s`", file, line, func, stmt);
switch(res) {
// Non-errno errors
case MAP_ERR_UNKNOWN:
case MAP_SUCCESS:
fprintf(stderr, err);
if(0)
// errno errors
default:
perror(err);
return 0;
}
}
}
#define map_handle_err(stmt) _map_handle_err(#stmt, __FILE__, __LINE__, __func__, stmt)
#endif /* _MAP_H */

@ -12,6 +12,8 @@
#include <tests.h>
#include <map.h>
void prog_info(FILE* out)
{
fprintf(out, PROG_NAME " v%s - " PROG_DESCRIPTION
@ -43,9 +45,15 @@ noreturn void usage_then_exit(int err, int argc, char** argv)
int main(int argc, char** argv)
{
TRACE("main start");
TRACE("main start with %d (pn: %s, a1: %s)", argc, argv[0], argv[1] ?: "<null>");
if(!argv[1] || !argv[2]) usage_then_exit(1, argc, argv);
map_t needle;
INFO("Mapping needle file `%s'", argv[1]);
if(!map_handle_err(map_file(argv[1], false, 0, 0, &needle))) return 2;
usage_then_exit(0, argc, argv);
if(!map_handle_err(map_free(needle))) return 3;
TRACE("main end");

@ -4,6 +4,7 @@
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <macros.h>
#include <map.h>
@ -12,17 +13,21 @@
static inline void _map_init(map_t *pOUT map)
{
memset(map, 0xff, sizeof(map_t));
TRACE("blanked %p->%lu to 0xff", map, sizeof(map_t));
}
static inline bool _map_is_file(const map_t* map)
{
TRACE("fd element of union is %x (%d)", map->file.fd, map->file.fd);
return map->file.fd > 0;
}
map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT map)
{
TRACE("mapping %lu bytes of fd %d (%s) from offset %lu to %p", size, fd, write ? "rw" : "ro", offset, map);
void* ptr = mmap(NULL, size, PROT_READ | (write ? PROT_WRITE : 0), MAP_SHARED, fd, offset);
if(ptr == MAP_FAILED) return MAP_ERR_MMAP;
TRACE("mapped %p->%lu", ptr, size);
map->file = (struct mm_file){
.origin = ptr,
.len = size,
@ -34,16 +39,31 @@ map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT ma
map_result_t map_file(const char* file, bool write, usize size, off_t offset, map_t *pOUT map)
{
TRACE("mapping %lu bytes of file `%s' (%s) from %lu to %p", size, file, write ? "rw" : "ro", offset, map);
int fd = open(file, write ? O_RDWR : O_RDONLY);
if(fd < 0) return MAP_ERR_OPEN;
TRACE("opened file %d", fd);
if(!size) {
TRACE("user asked for max-size map (size: 0), stating %d to find size...", fd);
struct stat st;
// Find size of file
if(fstat(fd, &st) != 0) return (close(fd), MAP_ERR_STAT);
TRACE("fstat() reports size is %lu", st.st_size);
size = st.st_size;
}
TRACE("passing fd %d, size %lu to `map_fd()`", fd, size);
return map_fd(fd, write, size, offset, map);
}
map_result_t map_anon(void* ptr, usize len, map_t *pOUT map)
{
TRACE("mapping anon at %p (%s) of size %lu (map %p)", ptr, ptr ? "fixed" : "dynamic", len, map);
ptr = mmap(ptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | (ptr ? MAP_FIXED : 0), -1, 0);
if(ptr==MAP_FAILED) return MAP_ERR_MMAP;
TRACE("mapped ptr %p->%lu", ptr, len);
// Make sure .file.fd is -1, so we can tell this is anon in `map_free()`.
_map_init(map);
map->anon = (struct mm_anon) {
@ -55,9 +75,30 @@ map_result_t map_anon(void* ptr, usize len, map_t *pOUT map)
map_result_t map_free(map_t map)
{
TRACE("unmapping %p->%lu", map.origin, map.len);
if( munmap(map.anon.origin, map.anon.len) != 0) return MAP_ERR_UNMAP;
if( _map_is_file(&map) ) {
TRACE("map is file, closing fd %d", map.file.fd);
if( close(map.file.fd) != 0 ) return MAP_ERR_CLOSE;
}
return MAP_SUCCESS;
}
const char* map_error_str(map_result_t res)
{
switch(res)
{
#define CASE(err, str) case err: return str
CASE(MAP_ERR_MMAP, "mmap() failed (creating a map)");
CASE(MAP_ERR_UNMAP, "munmap() failed (freeing a map)");
CASE(MAP_ERR_OPEN, "open() failed (mapping a filepath)");
CASE(MAP_ERR_CLOSE, "close() failed (freeing a file-map)");
CASE(MAP_ERR_STAT, "fstat() failed: (mapping a full filepath)");
CASE(MAP_SUCCESS, "success");
#undef CASE
default:
ERROR("unkown or invalid error code %d", (int)res);
return "unknown error";
}
}

Loading…
Cancel
Save