/* * 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-2018 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.com/ * * This software is maintained by Dave Mielke . */ #include "prologue.h" #include #include #include #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); }