blob: 2a493166ffcc9182f6e547a552ec6366fe268974 [file] [log] [blame] [edit]
/*
* BRLTTY - A background process providing access to the console screen (when in
* text mode) for a blind person using a refreshable braille display.
*
* Copyright (C) 1995-2023 by The BRLTTY Developers.
*
* BRLTTY comes with ABSOLUTELY NO WARRANTY.
*
* This is free software, placed under the terms of the
* GNU Lesser General Public License, as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any
* later version. Please see the file LICENSE-LGPL for details.
*
* Web Page: http://brltty.app/
*
* This software is maintained by Dave Mielke <dave@mielke.cc>.
*/
#include "prologue.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "addresses.h"
#include "log.h"
#include "dynld.h"
#include "program.h"
typedef struct {
void *address;
char name[0];
} AddressEntry;
static AddressEntry **addressTable = NULL;
static int addressCount = 0;
static int addressLimit = 0;
static void
exitAddressTable (void *data) {
if (addressTable) free(addressTable);
addressTable = NULL;
addressCount = 0;
addressLimit = 0;
}
static int
findAddressIndex (int *index, void *address) {
int first = 0;
int last = addressCount - 1;
while (first <= last) {
int current = (first + last) / 2;
AddressEntry *entry = addressTable[current];
if (entry->address == address) {
*index = current;
return 1;
}
if (address < entry->address) {
last = current - 1;
} else {
first = current + 1;
}
}
*index = first;
return 0;
}
static void
moveAddressSlice (int to, int from, int count) {
memmove(&addressTable[to], &addressTable[from], ARRAY_SIZE(addressTable, count));
}
static int
insertAddressEntry (int index, AddressEntry *entry) {
if (addressCount == addressLimit) {
int newLimit = addressLimit + 1;
AddressEntry **newTable = realloc(addressTable, ARRAY_SIZE(newTable, newLimit));
if (!newTable) {
logMallocError();
return 0;
}
if (!addressTable) {
onProgramExit("address-table", exitAddressTable, NULL);
}
addressTable = newTable;
addressLimit = newLimit;
}
moveAddressSlice(index+1, index, (addressCount++ - index));
addressTable[index] = entry;
return 1;
}
static void
removeAddressEntry (int index) {
free(addressTable[index]);
moveAddressSlice(index, index+1, (--addressCount - index));
}
int
setAddressName (void *address, const char *format, ...) {
char name[0X1000];
AddressEntry *entry;
size_t size;
{
va_list arguments;
va_start(arguments, format);
vsnprintf(name, sizeof(name), format, arguments);
va_end(arguments);
}
size = sizeof(*entry) + strlen(name) + 1;
if ((entry = malloc(size))) {
int index;
memset(entry, 0, sizeof(*entry));
entry->address = address;
strcpy(entry->name, name);
if (findAddressIndex(&index, address)) {
free(addressTable[index]);
addressTable[index] = entry;
return 1;
}
if (insertAddressEntry(index, entry)) return 1;
free(entry);
} else {
logMallocError();
}
return 0;
}
void
unsetAddressName (void *address) {
int index;
if (findAddressIndex(&index, address)) {
removeAddressEntry(index);
}
}
const char *
getAddressName (void *address, ptrdiff_t *offset) {
{
int index;
if (findAddressIndex(&index, address)) {
if (offset) *offset = 0;
return addressTable[index]->name;
}
}
return getSharedSymbolName(address, offset);
}