109 |
return 0; |
return 0; |
110 |
} |
} |
111 |
|
|
112 |
|
void |
113 |
|
pupa_dl_iterate (int (*hook) (pupa_dl_t mod)) |
114 |
|
{ |
115 |
|
pupa_dl_list_t l; |
116 |
|
|
117 |
|
for (l = pupa_dl_head; l; l = l->next) |
118 |
|
if (hook (l->mod)) |
119 |
|
break; |
120 |
|
} |
121 |
|
|
122 |
|
|
123 |
|
|
124 |
struct pupa_symbol |
struct pupa_symbol |
355 |
return pupa_errno; |
return pupa_errno; |
356 |
|
|
357 |
if (pupa_strcmp (name, "pupa_mod_init") == 0) |
if (pupa_strcmp (name, "pupa_mod_init") == 0) |
358 |
mod->init = (void (*) ()) sym->st_value; |
mod->init = (void (*) (pupa_dl_t)) sym->st_value; |
359 |
else if (pupa_strcmp (name, "pupa_mod_fini") == 0) |
else if (pupa_strcmp (name, "pupa_mod_fini") == 0) |
360 |
mod->fini = (void (*) ()) sym->st_value; |
mod->fini = (void (*) (void)) sym->st_value; |
361 |
break; |
break; |
362 |
|
|
363 |
case STT_SECTION: |
case STT_SECTION: |
382 |
pupa_dl_call_init (pupa_dl_t mod) |
pupa_dl_call_init (pupa_dl_t mod) |
383 |
{ |
{ |
384 |
if (mod->init) |
if (mod->init) |
385 |
(mod->init) (); |
(mod->init) (mod); |
386 |
} |
} |
387 |
|
|
388 |
static pupa_err_t |
static pupa_err_t |
438 |
m = pupa_dl_load (name); |
m = pupa_dl_load (name); |
439 |
if (! m) |
if (! m) |
440 |
return pupa_errno; |
return pupa_errno; |
441 |
|
|
442 |
|
pupa_dl_ref (m); |
443 |
|
|
444 |
dep = (pupa_dl_dep_t) pupa_malloc (sizeof (*dep)); |
dep = (pupa_dl_dep_t) pupa_malloc (sizeof (*dep)); |
445 |
if (! dep) |
if (! dep) |
456 |
return PUPA_ERR_NONE; |
return PUPA_ERR_NONE; |
457 |
} |
} |
458 |
|
|
459 |
|
int |
460 |
|
pupa_dl_ref (pupa_dl_t mod) |
461 |
|
{ |
462 |
|
return ++mod->ref_count; |
463 |
|
} |
464 |
|
|
465 |
|
int |
466 |
|
pupa_dl_unref (pupa_dl_t mod) |
467 |
|
{ |
468 |
|
int ret; |
469 |
|
|
470 |
|
ret = --mod->ref_count; |
471 |
|
if (ret <= 0) |
472 |
|
pupa_dl_unload (mod); |
473 |
|
|
474 |
|
return ret; |
475 |
|
} |
476 |
|
|
477 |
/* Load a module from core memory. */ |
/* Load a module from core memory. */ |
478 |
pupa_dl_t |
pupa_dl_t |
479 |
pupa_dl_load_core (void *addr, pupa_size_t size) |
pupa_dl_load_core (void *addr, pupa_size_t size) |
543 |
goto failed; |
goto failed; |
544 |
|
|
545 |
mod = pupa_dl_load_core (core, size); |
mod = pupa_dl_load_core (core, size); |
546 |
|
mod->ref_count = 0; |
547 |
|
|
548 |
failed: |
failed: |
549 |
pupa_file_close (file); |
pupa_file_close (file); |
563 |
|
|
564 |
mod = pupa_dl_get (name); |
mod = pupa_dl_get (name); |
565 |
if (mod) |
if (mod) |
566 |
{ |
return mod; |
|
mod->ref_count++; |
|
|
return mod; |
|
|
} |
|
567 |
|
|
568 |
if (! pupa_dl_dir) |
if (! pupa_dl_dir) |
569 |
pupa_fatal ("module dir is not initialized yet"); |
pupa_fatal ("module dir is not initialized yet"); |
587 |
} |
} |
588 |
|
|
589 |
/* Unload the module MOD. */ |
/* Unload the module MOD. */ |
590 |
void |
int |
591 |
pupa_dl_unload (pupa_dl_t mod) |
pupa_dl_unload (pupa_dl_t mod) |
592 |
{ |
{ |
593 |
pupa_dl_dep_t dep, depn; |
pupa_dl_dep_t dep, depn; |
594 |
pupa_dl_segment_t seg, segn; |
pupa_dl_segment_t seg, segn; |
595 |
|
|
596 |
if (--mod->ref_count > 0) |
if (mod->ref_count > 0) |
597 |
return; |
return 0; |
598 |
|
|
599 |
if (mod->fini) |
if (mod->fini) |
600 |
(mod->fini) (); |
(mod->fini) (); |
605 |
for (dep = mod->dep; dep; dep = depn) |
for (dep = mod->dep; dep; dep = depn) |
606 |
{ |
{ |
607 |
depn = dep->next; |
depn = dep->next; |
608 |
pupa_dl_unload (dep->mod); |
pupa_dl_unref (dep->mod); |
609 |
pupa_free (dep); |
pupa_free (dep); |
610 |
} |
} |
611 |
|
|
618 |
|
|
619 |
pupa_free (mod->name); |
pupa_free (mod->name); |
620 |
pupa_free (mod); |
pupa_free (mod); |
621 |
|
return 1; |
622 |
|
} |
623 |
|
|
624 |
|
/* Unload unneeded modules. */ |
625 |
|
void |
626 |
|
pupa_dl_unload_unneeded (void) |
627 |
|
{ |
628 |
|
/* Because pupa_dl_remove modifies the list of modules, this |
629 |
|
implementation is tricky. */ |
630 |
|
pupa_dl_list_t p = pupa_dl_head; |
631 |
|
|
632 |
|
while (p) |
633 |
|
{ |
634 |
|
if (pupa_dl_unload (p->mod)) |
635 |
|
{ |
636 |
|
p = pupa_dl_head; |
637 |
|
continue; |
638 |
|
} |
639 |
|
|
640 |
|
p = p->next; |
641 |
|
} |
642 |
|
} |
643 |
|
|
644 |
|
/* Unload all modules. */ |
645 |
|
void |
646 |
|
pupa_dl_unload_all (void) |
647 |
|
{ |
648 |
|
while (pupa_dl_head) |
649 |
|
{ |
650 |
|
pupa_dl_list_t p; |
651 |
|
|
652 |
|
pupa_dl_unload_unneeded (); |
653 |
|
|
654 |
|
/* Force to decrement the ref count. This will purge pre-loaded |
655 |
|
modules and manually inserted modules. */ |
656 |
|
for (p = pupa_dl_head; p; p = p->next) |
657 |
|
p->mod->ref_count--; |
658 |
|
} |
659 |
} |
} |
660 |
|
|
661 |
void |
void |
662 |
pupa_dl_init (const char *dir) |
pupa_dl_set_prefix (const char *dir) |
663 |
{ |
{ |
664 |
pupa_dl_dir = (char *) dir; |
pupa_dl_dir = (char *) dir; |
665 |
} |
} |
666 |
|
|
667 |
|
const char * |
668 |
|
pupa_dl_get_prefix (void) |
669 |
|
{ |
670 |
|
return pupa_dl_dir; |
671 |
|
} |