mapi: Delete dynamic stub generation.

Since Mesa drivers are now version-locked to the loader, that means that
we never need to support a newer hardware driver than the loader, and thus
don't need to generate dynamic dispatch stubs.  This is great news, given
that we don't test those paths, and it involved delightful features like
arrays of hex for code to be pasted into executable memory.

More code removal will follow, this is the first cut of "don't generate,
and DCE generation code".

Fixes: #9158

Acked-by: Marek Olšák <marek.olsak@amd.com>
Acked-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23451>
This commit is contained in:
Emma Anholt 2023-06-05 14:16:15 -07:00 committed by Marge Bot
parent 3033252966
commit 398a8d43dc
11 changed files with 18 additions and 683 deletions

View file

@ -71,17 +71,6 @@ entry_get_public(int slot)
return public_entries[slot];
}
mapi_func
entry_generate(int slot)
{
return NULL;
}
void
entry_patch(mapi_func entry, int slot)
{
}
#endif /* MAPI_MODE_BRIDGE */
#if defined(_WIN32) && defined(_WINDOWS_)

View file

@ -37,10 +37,4 @@ entry_patch_public(void);
mapi_func
entry_get_public(int slot);
mapi_func
entry_generate(int slot);
void
entry_patch(mapi_func entry, int slot);
#endif /* _ENTRY_H_ */

View file

@ -69,7 +69,6 @@ __asm__(".text\n"
#ifndef MAPI_MODE_BRIDGE
#include <string.h>
#include "u_execmem.h"
void
entry_patch_public(void)
@ -85,68 +84,4 @@ entry_get_public(int slot)
return (mapi_func) (ppc64le_entry_start + slot * PPC64LE_ENTRY_SIZE);
}
__asm__(".text\n");
__asm__("ppc64le_dispatch_tls:\n\t"
" addis 3, 2, _glapi_tls_Dispatch@got@tprel@ha\n\t"
" ld 3, _glapi_tls_Dispatch@got@tprel@l(3)\n\t"
" blr\n"
);
extern uint64_t ppc64le_dispatch_tls();
static const uint32_t code_templ[] = {
// This should be functionally the same code as would be generated from
// the STUB_ASM_CODE macro, but defined as a buffer.
// This is used to generate new dispatch stubs. Mesa will copy this
// data to the dispatch stub, and then it will patch the slot number and
// any addresses that it needs to.
// NOTE!!! NOTE!!! NOTE!!!
// This representation is correct for both little- and big-endian systems.
// However, more work needs to be done for big-endian Linux because it
// adheres to an older, AIX-compatible ABI that uses function descriptors.
// 1000:
0x7C0802A6, // <ENTRY+00>: mflr 0
0xF8010010, // <ENTRY+04>: std 0, 16(1)
0xE96C0028, // <ENTRY+08>: ld 11, 9000f-1000b+0(12)
0x7D6B6A14, // <ENTRY+12>: add 11, 11, 13
0xE96B0000, // <ENTRY+16>: ld 11, 0(11)
0xE80C0030, // <ENTRY+20>: ld 0, 9000f-1000b+8(12)
0x7D8B002A, // <ENTRY+24>: ldx 12, 11, 0
0x7D8903A6, // <ENTRY+28>: mtctr 12
0x4E800420, // <ENTRY+32>: bctr
0x60000000, // <ENTRY+36>: nop
// 9000:
0, 0, // <ENTRY+40>: .quad _glapi_tls_Dispatch
0, 0 // <ENTRY+48>: .quad <slot>*8
};
static const uint64_t TEMPLATE_OFFSET_TLS_ADDR = sizeof(code_templ) - 2*8;
static const uint64_t TEMPLATE_OFFSET_SLOT = sizeof(code_templ) - 1*8;
void
entry_patch(mapi_func entry, int slot)
{
char *code = (char *) entry;
*((uint64_t *) (code + TEMPLATE_OFFSET_TLS_ADDR)) = ppc64le_dispatch_tls();
*((uint64_t *) (code + TEMPLATE_OFFSET_SLOT)) = slot * sizeof(mapi_func);
}
mapi_func
entry_generate(int slot)
{
char *code;
mapi_func entry;
code = u_execmem_alloc(sizeof(code_templ));
if (!code)
return NULL;
memcpy(code, code_templ, sizeof(code_templ));
entry = (mapi_func) code;
entry_patch(entry, slot);
return entry;
}
#endif /* MAPI_MODE_BRIDGE */

View file

@ -72,7 +72,6 @@ __asm__(".text\n"
#ifndef MAPI_MODE_BRIDGE
#include <string.h>
#include "u_execmem.h"
void
entry_patch_public(void)
@ -88,56 +87,5 @@ entry_get_public(int slot)
return (mapi_func) (x86_64_entry_start + slot * 32);
}
void
entry_patch(mapi_func entry, int slot)
{
char *code = (char *) entry;
int offset = 12;
#ifdef __ILP32__
offset = 13;
#endif
*((unsigned int *) (code + offset)) = slot * sizeof(mapi_func);
}
mapi_func
entry_generate(int slot)
{
const char code_templ[] = {
#ifndef __ILP32__
/* movq %fs:0, %r11 */
0x64, 0x4c, 0x8b, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00,
/* jmp *0x1234(%r11) */
0x41, 0xff, 0xa3, 0x34, 0x12, 0x00, 0x00,
#else
/* movl %fs:0, %r11d */
0x64, 0x44, 0x8b, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00,
/* movl 0x1234(%r11d), %r11d */
0x67, 0x45, 0x8b, 0x9b, 0x34, 0x12, 0x00, 0x00,
/* jmp *%r11 */
0x41, 0xff, 0xe3,
#endif
};
unsigned long long addr;
char *code;
mapi_func entry;
__asm__("movq _glapi_tls_Dispatch@GOTTPOFF(%%rip), %0"
: "=r" (addr));
if ((addr >> 32) != 0xffffffff)
return NULL;
addr &= 0xffffffff;
code = u_execmem_alloc(sizeof(code_templ));
if (!code)
return NULL;
memcpy(code, code_templ, sizeof(code_templ));
*((unsigned int *) (code + 5)) = addr;
entry = (mapi_func) code;
entry_patch(entry, slot);
return entry;
}
#endif /* MAPI_MODE_BRIDGE */

View file

@ -85,8 +85,6 @@ __asm__(".text");
#ifndef MAPI_MODE_BRIDGE
#include "u_execmem.h"
extern unsigned long
x86_current_tls();
@ -114,7 +112,7 @@ entry_get_public(int slot)
return (mapi_func) (x86_entry_start + slot * X86_ENTRY_SIZE);
}
void
static void
entry_patch(mapi_func entry, int slot)
{
char *code = (char *) entry;
@ -131,11 +129,7 @@ entry_generate_or_patch(int slot, char *code, size_t size)
};
mapi_func entry;
if (code == NULL) {
size = sizeof(code_templ);
code = u_execmem_alloc(size);
}
if (!code || size < sizeof(code_templ))
if (size < sizeof(code_templ))
return NULL;
memcpy(code, code_templ, sizeof(code_templ));
@ -147,10 +141,4 @@ entry_generate_or_patch(int slot, char *code, size_t size)
return entry;
}
mapi_func
entry_generate(int slot)
{
return entry_generate_or_patch(slot, NULL, 0);
}
#endif /* MAPI_MODE_BRIDGE */

View file

@ -33,7 +33,6 @@
#include "c11/threads.h"
#include "glapi/glapi_priv.h"
#include "u_execmem.h"
#ifdef USE_X86_ASM
@ -81,46 +80,6 @@ init_glapi_relocs( void )
#endif
}
/**
* Generate a dispatch function (entrypoint) which jumps through
* the given slot number (offset) in the current dispatch table.
* We need assembly language in order to accomplish this.
*/
_glapi_proc
generate_entrypoint(unsigned int functionOffset)
{
/* 32 is chosen as something of a magic offset. For x86, the dispatch
* at offset 32 is the first one where the offset in the
* "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
*/
const GLubyte * const template_func = gl_dispatch_functions_start
+ (DISPATCH_FUNCTION_SIZE * 32);
GLubyte * const code = (GLubyte *) u_execmem_alloc(DISPATCH_FUNCTION_SIZE);
if ( code != NULL ) {
(void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
}
return (_glapi_proc) code;
}
/**
* This function inserts a new dispatch offset into the assembly language
* stub that was generated with the preceeding function.
*/
void
fill_in_entrypoint_offset(_glapi_proc entrypoint, unsigned int offset)
{
GLubyte * const code = (GLubyte *) entrypoint;
*((unsigned int *)(code + 8)) = 4 * offset;
}
#elif defined(USE_SPARC_ASM)
extern void __glapi_sparc_icache_flush(unsigned int *);
@ -161,43 +120,6 @@ init_glapi_relocs( void )
}
_glapi_proc
generate_entrypoint(GLuint functionOffset)
{
static const unsigned int template[] = {
0x07000000, /* sethi %hi(0), %g3 */
0x8210000f, /* mov %o7, %g1 */
0x40000000, /* call */
0x9e100001, /* mov %g1, %o7 */
};
extern unsigned int __glapi_sparc_tls_stub;
unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub;
unsigned int *code = (unsigned int *) u_execmem_alloc(sizeof(template));
if (code) {
code[0] = template[0] | (functionOffset & 0x3fffff);
code[1] = template[1];
__glapi_sparc_icache_flush(&code[0]);
code[2] = template[2] |
(((call_dest - ((unsigned long) &code[2]))
>> 2) & 0x3fffffff);
code[3] = template[3];
__glapi_sparc_icache_flush(&code[2]);
}
return (_glapi_proc) code;
}
void
fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
{
unsigned int *code = (unsigned int *) entrypoint;
code[0] &= ~0x3fffff;
code[0] |= (offset * sizeof(void *)) & 0x3fffff;
__glapi_sparc_icache_flush(&code[0]);
}
#else /* USE_*_ASM */
static void
@ -205,23 +127,6 @@ init_glapi_relocs( void )
{
}
_glapi_proc
generate_entrypoint(GLuint functionOffset)
{
(void) functionOffset;
return NULL;
}
void
fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
{
/* an unimplemented architecture */
(void) entrypoint;
(void) offset;
}
#endif /* USE_*_ASM */

View file

@ -37,10 +37,6 @@
#include "glapitable.h"
#define FIRST_DYNAMIC_OFFSET (sizeof(struct _glapi_table) / sizeof(void *))
/**********************************************************************
* Static function management.
*/
@ -156,177 +152,12 @@ struct _glapi_function {
* - 'd' for \c GLdouble and \c GLclampd
*/
const char * parameter_signature;
/**
* Offset in the dispatch table where the pointer to the real function is
* located. If the driver has not requested that the named function be
* added to the dispatch table, this will have the value ~0.
*/
unsigned dispatch_offset;
/**
* Pointer to the dispatch stub for the named function.
*
* \todo
* The semantic of this field should be changed slightly. Currently, it
* is always expected to be non-\c NULL. However, it would be better to
* only allocate the entry-point stub when the application requests the
* function via \c glXGetProcAddress. This would save memory for all the
* functions that the driver exports but that the application never wants
* to call.
*/
_glapi_proc dispatch_stub;
};
static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
static GLuint NumExtEntryPoints = 0;
static struct _glapi_function *
get_extension_proc(const char *funcName)
{
GLuint i;
for (i = 0; i < NumExtEntryPoints; i++) {
if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
return & ExtEntryTable[i];
}
}
return NULL;
}
static GLint
get_extension_proc_offset(const char *funcName)
{
const struct _glapi_function * const f = get_extension_proc( funcName );
if (f == NULL) {
return -1;
}
return f->dispatch_offset;
}
static _glapi_proc
get_extension_proc_address(const char *funcName)
{
const struct _glapi_function * const f = get_extension_proc( funcName );
if (f == NULL) {
return NULL;
}
return f->dispatch_stub;
}
static const char *
get_extension_proc_name(GLuint offset)
{
GLuint i;
for (i = 0; i < NumExtEntryPoints; i++) {
if (ExtEntryTable[i].dispatch_offset == offset) {
return ExtEntryTable[i].name;
}
}
return NULL;
}
/**
* strdup() is actually not a standard ANSI C or POSIX routine.
* Irix will not define it if ANSI mode is in effect.
*/
static char *
str_dup(const char *str)
{
char *copy;
copy = malloc(strlen(str) + 1);
if (!copy)
return NULL;
strcpy(copy, str);
return copy;
}
/**
* Generate new entrypoint
*
* Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver
* calls \c _glapi_add_dispatch we'll put in the proper offset. If that
* never happens, and the user calls this function, he'll segfault. That's
* what you get when you try calling a GL function that doesn't really exist.
*
* \param funcName Name of the function to create an entry-point for.
*
* \sa _glapi_add_entrypoint
*/
static struct _glapi_function *
add_function_name( const char * funcName )
{
struct _glapi_function * entry = NULL;
_glapi_proc entrypoint = NULL;
char * name_dup = NULL;
if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS)
return NULL;
if (funcName == NULL)
return NULL;
name_dup = str_dup(funcName);
if (name_dup == NULL)
return NULL;
entrypoint = generate_entrypoint(~0);
if (entrypoint == NULL) {
free(name_dup);
return NULL;
}
entry = & ExtEntryTable[NumExtEntryPoints];
NumExtEntryPoints++;
entry->name = name_dup;
entry->parameter_signature = NULL;
entry->dispatch_offset = ~0;
entry->dispatch_stub = entrypoint;
return entry;
}
static struct _glapi_function *
set_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset )
{
char * sig_dup = NULL;
if (signature == NULL)
return NULL;
sig_dup = str_dup(signature);
if (sig_dup == NULL)
return NULL;
fill_in_entrypoint_offset(entry->dispatch_stub, offset);
entry->parameter_signature = sig_dup;
entry->dispatch_offset = offset;
return entry;
}
/**
* Fill-in the dispatch stub for the named function.
*
* This function is intended to be called by a hardware driver. When called,
* a dispatch stub may be created for the function. A pointer to this
* dispatch function will be returned by glXGetProcAddress.
* This function is intended to be called by Mesa core, returning the dispatch
* table offset for the passed set of aliased gl* functions.
*
* \param function_names Array of pointers to function names that should
* share a common dispatch offset.
@ -371,18 +202,11 @@ set_entry_info( struct _glapi_function * entry, const char * signature, unsigned
int
_glapi_add_dispatch(const char *const *function_names, const char *parameter_signature)
{
static int next_dynamic_offset = FIRST_DYNAMIC_OFFSET;
const char *const real_sig = (parameter_signature != NULL) ? parameter_signature : "";
struct _glapi_function *entry[8];
GLboolean is_static[8];
unsigned i;
int offset = ~0;
init_glapi_relocs_once();
(void)memset(is_static, 0, sizeof(is_static));
(void)memset(entry, 0, sizeof(entry));
/* Find the _single_ dispatch offset for all function names that already
* exist (and have a dispatch offset).
*/
@ -399,8 +223,6 @@ _glapi_add_dispatch(const char *const *function_names, const char *parameter_sig
static_offset = get_static_proc_offset(funcName);
if (static_offset >= 0) {
is_static[i] = GL_TRUE;
/* FIXME: Make sure the parameter signatures match! How do we get
* FIXME: the parameter signature for static functions?
*/
@ -410,65 +232,8 @@ _glapi_add_dispatch(const char *const *function_names, const char *parameter_sig
}
offset = static_offset;
continue;
}
/* search added extension functions */
entry[i] = get_extension_proc(funcName);
if (entry[i] != NULL) {
extension_offset = entry[i]->dispatch_offset;
/* The offset may be ~0 if the function name was added by
* glXGetProcAddress but never filled in by the driver.
*/
if (extension_offset == ~0) {
continue;
}
if (strcmp(real_sig, entry[i]->parameter_signature) != 0) {
return -1;
}
if ((offset != ~0) && (extension_offset != offset)) {
return -1;
}
offset = extension_offset;
}
}
/* If all function names are either new (or with no dispatch offset),
* allocate a new dispatch offset.
*/
if (offset == ~0) {
offset = next_dynamic_offset;
next_dynamic_offset++;
}
/* Fill in the dispatch offset for the new function names (and those with
* no dispatch offset).
*/
for (i = 0; function_names[i] != NULL; i++) {
if (is_static[i]) {
continue;
}
/* generate entrypoints for new function names */
if (entry[i] == NULL) {
entry[i] = add_function_name(function_names[i]);
if (entry[i] == NULL) {
/* FIXME: Possible memory leak here. */
return -1;
}
}
if (entry[i]->dispatch_offset == ~0) {
set_entry_info(entry[i], real_sig, offset);
} else {
return -1;
}
}
@ -481,13 +246,6 @@ _glapi_add_dispatch(const char *const *function_names, const char *parameter_sig
GLint
_glapi_get_proc_offset(const char *funcName)
{
GLint offset;
/* search extension functions first */
offset = get_extension_proc_offset(funcName);
if (offset >= 0)
return offset;
/* search static functions */
return get_static_proc_offset(funcName);
}
@ -510,22 +268,12 @@ _glapi_get_proc_address(const char *funcName)
if (!funcName || funcName[0] != 'g' || funcName[1] != 'l')
return NULL;
/* search extension functions first */
func = get_extension_proc_address(funcName);
if (func)
return func;
/* search static functions */
func = get_static_proc_address(funcName);
if (func)
return func;
/* generate entrypoint, dispatch offset must be filled in by the driver */
entry = add_function_name(funcName);
if (entry == NULL)
return NULL;
return entry->dispatch_stub;
return NULL;
}
@ -563,11 +311,5 @@ _glapi_get_proc_name(GLuint offset)
GLuint
_glapi_get_dispatch_table_size(void)
{
/*
* The dispatch table size (number of entries) is the size of the
* _glapi_table struct plus the number of dynamic entries we can add.
* The extra slots can be filled in by DRI drivers that register new
* extension functions.
*/
return FIRST_DYNAMIC_OFFSET + MAX_EXTENSION_FUNCS;
return sizeof(struct _glapi_table) / sizeof(void *);
}

View file

@ -40,14 +40,6 @@ extern void
init_glapi_relocs_once(void);
extern _glapi_proc
generate_entrypoint(unsigned int functionOffset);
extern void
fill_in_entrypoint_offset(_glapi_proc entrypoint, unsigned int offset);
extern _glapi_proc
get_entrypoint_address(unsigned int functionOffset);
@ -64,17 +56,6 @@ get_entrypoint_address(unsigned int functionOffset);
#endif
/**
* Number of extension functions which we can dynamically add at runtime.
*
* Number of extension functions is also subject to the size of backing exec
* mem we allocate. For the common case of dispatch stubs with size 16 bytes,
* the two limits will be hit simultaneously. For larger dispatch function
* sizes, MAX_EXTENSION_FUNCS is effectively reduced.
*/
#define MAX_EXTENSION_FUNCS 256
#ifdef __cplusplus
}
#endif

View file

@ -55,9 +55,8 @@ _glapi_get_dispatch_table_size(void)
/**
* Fill-in the dispatch stub for the named function.
*
* This function is intended to be called by a hardware driver. When called,
* a dispatch stub may be created created for the function. A pointer to this
* dispatch function will be returned by glXGetProcAddress.
* This function is intended to be called by Mesa core, returning the dispatch
* table offset for the passed set of aliased gl* functions.
*
* \param function_names Array of pointers to function names that should
* share a common dispatch offset.
@ -91,12 +90,9 @@ int
_glapi_add_dispatch( const char * const * function_names,
const char * parameter_signature )
{
const struct mapi_stub *function_stubs[8];
const struct mapi_stub *alias = NULL;
unsigned i;
(void) memset((void*)function_stubs, 0, sizeof(function_stubs));
/* find the missing stubs, and decide the alias */
for (i = 0; function_names[i] != NULL && i < 8; i++) {
const char * funcName = function_names[i];
@ -109,7 +105,7 @@ _glapi_add_dispatch( const char * const * function_names,
stub = stub_find_public(funcName);
if (!stub)
stub = stub_find_dynamic(funcName, 0);
return -1;
slot = (stub) ? stub_get_slot(stub) : -1;
if (slot >= 0) {
@ -118,62 +114,20 @@ _glapi_add_dispatch( const char * const * function_names,
/* use the first existing stub as the alias */
if (!alias)
alias = stub;
function_stubs[i] = stub;
}
}
/* generate missing stubs */
for (i = 0; function_names[i] != NULL && i < 8; i++) {
const char * funcName = function_names[i] + 2;
struct mapi_stub *stub;
if (function_stubs[i])
continue;
stub = stub_find_dynamic(funcName, 1);
if (!stub)
return -1;
stub_fix_dynamic(stub, alias);
if (!alias)
alias = stub;
}
return (alias) ? stub_get_slot(alias) : -1;
}
#if defined(ANDROID) && ANDROID_API_LEVEL <= 30
static int is_debug_marker_func(const char *name)
{
return (!strcmp(name, "InsertEventMarkerEXT") ||
!strcmp(name, "PushGroupMarkerEXT") ||
!strcmp(name, "PopGroupMarkerEXT"));
}
#endif
static const struct mapi_stub *
_glapi_get_stub(const char *name, int generate)
_glapi_get_stub(const char *name)
{
const struct mapi_stub *stub;
if (!name || name[0] != 'g' || name[1] != 'l')
return NULL;
name += 2;
stub = stub_find_public(name);
#if defined(ANDROID) && ANDROID_API_LEVEL <= 30
/* Android framework till API Level 30 uses function pointers from
* eglGetProcAddress without checking GL_EXT_debug_marker.
* Make sure we don't return stub function pointers if we don't
* support GL_EXT_debug_marker */
if (!stub && !is_debug_marker_func(name))
#else
if (!stub)
#endif
stub = stub_find_dynamic(name, generate);
return stub;
return stub_find_public(name);
}
/**
@ -182,7 +136,7 @@ _glapi_get_stub(const char *name, int generate)
int
_glapi_get_proc_offset(const char *funcName)
{
const struct mapi_stub *stub = _glapi_get_stub(funcName, 0);
const struct mapi_stub *stub = _glapi_get_stub(funcName);
return (stub) ? stub_get_slot(stub) : -1;
}
@ -194,7 +148,7 @@ _glapi_get_proc_offset(const char *funcName)
_glapi_proc
_glapi_get_proc_address(const char *funcName)
{
const struct mapi_stub *stub = _glapi_get_stub(funcName, 1);
const struct mapi_stub *stub = _glapi_get_stub(funcName);
return (stub) ? (_glapi_proc) stub_get_addr(stub) : NULL;
}

View file

@ -48,10 +48,6 @@ struct mapi_stub {
#define MAPI_TMP_PUBLIC_STUBS
#include "mapi_tmp.h"
static struct mapi_stub dynamic_stubs[MAPI_TABLE_NUM_DYNAMIC];
static int num_dynamic_stubs;
static int next_dynamic_slot = MAPI_TABLE_NUM_STATIC;
void
stub_init_once(void)
{
@ -81,69 +77,6 @@ stub_find_public(const char *name)
ARRAY_SIZE(public_stubs), sizeof(public_stubs[0]), stub_compare);
}
/**
* Add a dynamic stub.
*/
static struct mapi_stub *
stub_add_dynamic(const char *name)
{
struct mapi_stub *stub;
int idx;
idx = num_dynamic_stubs;
/* minus 1 to make sure we can never reach the last slot */
if (idx >= MAPI_TABLE_NUM_DYNAMIC - 1)
return NULL;
stub = &dynamic_stubs[idx];
/* dispatch to the last slot, which is reserved for no-op */
stub->addr = entry_generate(
MAPI_TABLE_NUM_STATIC + MAPI_TABLE_NUM_DYNAMIC - 1);
if (!stub->addr)
return NULL;
stub->name = (const void *) strdup(name);
/* to be fixed later */
stub->slot = -1;
num_dynamic_stubs = idx + 1;
return stub;
}
/**
* Return the dynamic stub with the given name. If no such stub exists and
* generate is true, a new stub is generated.
*/
struct mapi_stub *
stub_find_dynamic(const char *name, int generate)
{
static simple_mtx_t dynamic_mutex = SIMPLE_MTX_INITIALIZER;
struct mapi_stub *stub = NULL;
int count, i;
simple_mtx_lock(&dynamic_mutex);
if (generate)
assert(!stub_find_public(name));
count = num_dynamic_stubs;
for (i = 0; i < count; i++) {
if (strcmp(name, (const char *) dynamic_stubs[i].name) == 0) {
stub = &dynamic_stubs[i];
break;
}
}
/* generate a dynamic stub */
if (generate && !stub)
stub = stub_add_dynamic(name);
simple_mtx_unlock(&dynamic_mutex);
return stub;
}
static const struct mapi_stub *
search_table_by_slot(const struct mapi_stub *table, size_t num_entries,
@ -162,26 +95,7 @@ stub_find_by_slot(int slot)
{
const struct mapi_stub *stub =
search_table_by_slot(public_stubs, ARRAY_SIZE(public_stubs), slot);
if (stub)
return stub;
return search_table_by_slot(dynamic_stubs, num_dynamic_stubs, slot);
}
void
stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias)
{
int slot;
if (stub->slot >= 0)
return;
if (alias)
slot = alias->slot;
else
slot = next_dynamic_slot++;
entry_patch(stub->addr, slot);
stub->slot = slot;
return stub;
}
/**
@ -190,15 +104,7 @@ stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias)
const char *
stub_get_name(const struct mapi_stub *stub)
{
const char *name;
if (stub >= public_stubs &&
stub < public_stubs + ARRAY_SIZE(public_stubs))
name = &public_string_pool[(size_t) stub->name];
else
name = (const char *) stub->name;
return name;
return &public_string_pool[(size_t) stub->name];
}
/**
@ -216,6 +122,5 @@ stub_get_slot(const struct mapi_stub *stub)
mapi_func
stub_get_addr(const struct mapi_stub *stub)
{
assert(stub->addr || (unsigned int) stub->slot < MAPI_TABLE_NUM_STATIC);
return (stub->addr) ? stub->addr : entry_get_public(stub->slot);
return entry_get_public(stub->slot);
}

View file

@ -38,15 +38,9 @@ stub_init_once(void);
const struct mapi_stub *
stub_find_public(const char *name);
struct mapi_stub *
stub_find_dynamic(const char *name, int generate);
const struct mapi_stub *
stub_find_by_slot(int slot);
void
stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias);
const char *
stub_get_name(const struct mapi_stub *stub);