Почему ctypes также загружает стандартные функции библиотеки C и как я могу это предотвратить? [дубликат]Python

Программы на Python
Anonymous
Почему ctypes также загружает стандартные функции библиотеки C и как я могу это предотвратить? [дубликат]

Сообщение Anonymous »

РЕДАКТИРОВАТЬ: Проблема была совершенно неправильно диагностирована и была связана с связыванием, а не с самим ctypes (libc неявно связана с gcc), и я нашел фактическое решение где-то еще. Отсюда и флаг дублирования.
  • Загрузка самодельной общей библиотеки с помощью ctypes, похоже, обеспечивает доступ к стандартные функции библиотеки C каким-то образом.
    Почему?
    Я ожидал увидеть какую-то ошибку AttributeError при попытке использовать MRE ниже.
  • Как я могу ограничить такое поведение (если возможно)?
  • [тайбрейкер]: как разрешается имя функции при попытке доступа к ней, и если моя самодельная библиотека переопределяет функцию стандартной библиотеки C?
Контекст и мотив:
Насколько я понимаю из документации, он должен возвращать представление загруженного общего ресурса библиотека. Но похоже, что он ведет себя как нечто большее.
Я столкнулся с таким поведением, когда работал над собственной реализацией некоторых функций стандартной библиотеки C, что приводило к неожиданным результатам при попытке тестирования. это с помощью инструментов Python с использованием ctypes.
Основная проблема в том, что редактирование моего кода не оказывает никакого влияния на поведение загруженных внешних функций и результаты тестов. Теперь становится ясно, что мои тесты на самом деле запускали функции системы, а не мои собственные.
Хотя использование разных символов (например, добавление префикса к именам моих самодельных функций) является простым обходным решением. , мне бы очень хотелось понять, почему этот доступ к функциям, которые я никогда явно не использовал и не включал, предоставляется ctypes очевидно из ниоткуда.
Я не нашел никаких следов такого поведения в документация ctypes.

MRE:

Код: Выделить всё

#!/usr/bin/env python3

import ctypes
import os

my_lib = ctypes.CDLL(os.path.abspath("libfoo.so"))

# I expect this to work (It does).
print(f"{my_lib.foo = }")
# I expect this to fail (It doesn't).
print(f"{my_lib.strncmp = }")
# I expect this to fail (It does).
print(f"{my_lib.bar = }")

Код: Выделить всё

    global foo

foo:
ret
  • сеанс оболочки:

Код: Выделить всё

$ make
nasm -f elf64 -o foo.o foo.s
gcc -shared -o libfoo.so foo.o
$ nm -a libfoo.so
0000000000000000 a
w __cxa_finalize@GLIBC_2.2.5
0000000000004000 d __dso_handle
0000000000003e48 d _DYNAMIC
00000000000010f4 t _fini
00000000000010f0 T foo
0000000000000000 a foo.s
0000000000003fe8 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000004008 d __TMC_END__
$ ./test.py
my_lib.foo = 
my_lib.strncmp = 
Traceback (most recent call last):
File "/home/vmonteco/code/MREs/MRE_ctypes_give_access_to_stdlib/./test.py", line 13, in 
print(f"{my_lib.bar = }")
File "/home/vmonteco/.pyenv/versions/3.10.14/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__
func = self.__getitem__(name)
File "/home/vmonteco/.pyenv/versions/3.10.14/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /home/vmonteco/code/MREs/MRE_ctypes_give_access_to_stdlib/libfoo.so: undefined symbol: bar
$ ldd libfoo.so
linux-vdso.so.1 (0x00007610a363b000)
libc.so.6 =>  /usr/lib/libc.so.6 (0x00007610a341d000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007610a363d000)
$ readelf -ld libfoo.so

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 8 program headers, starting at offset 64

Program Headers:
Type           Offset             VirtAddr           PhysAddr
FileSiz            MemSiz              Flags  Align
LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000428 0x0000000000000428  R      0x1000
LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
0x0000000000000101 0x0000000000000101  R E    0x1000
LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
0x0000000000000004 0x0000000000000004  R      0x1000
LOAD           0x0000000000002e38 0x0000000000003e38 0x0000000000003e38
0x00000000000001d0 0x00000000000001d8  RW     0x1000
DYNAMIC        0x0000000000002e48 0x0000000000003e48 0x0000000000003e48
0x0000000000000180 0x0000000000000180  RW     0x8
NOTE           0x0000000000000200 0x0000000000000200 0x0000000000000200
0x0000000000000024 0x0000000000000024  R      0x4
GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000  RW     0x10
GNU_RELRO      0x0000000000002e38 0x0000000000003e38 0x0000000000003e38
0x00000000000001c8 0x00000000000001c8  R      0x1

Section to Segment mapping:
Segment Sections...
00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn
01     .init .text .fini
02     .eh_frame
03     .init_array .fini_array .dynamic .got .got.plt .data .bss
04     .dynamic
05     .note.gnu.build-id
06
07     .init_array .fini_array .dynamic .got .got.plt

Dynamic section at offset 0x2e48 contains 20 entries:
Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x000000000000000c (INIT)               0x1000
0x000000000000000d (FINI)               0x10f4
0x0000000000000019 (INIT_ARRAY)         0x3e38
0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
0x000000000000001a (FINI_ARRAY)         0x3e40
0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
0x000000006ffffef5 (GNU_HASH)           0x228
0x0000000000000005 (STRTAB)             0x2e0
0x0000000000000006 (SYMTAB)             0x250
0x000000000000000a (STRSZ)              111 (bytes)
0x000000000000000b (SYMENT)             24 (bytes)
0x0000000000000007 (RELA)               0x380
0x0000000000000008 (RELASZ)             168 (bytes)
0x0000000000000009 (RELAENT)            24 (bytes)
0x000000006ffffffe (VERNEED)            0x360
0x000000006fffffff (VERNEEDNUM)         1
0x000000006ffffff0 (VERSYM)             0x350
0x000000006ffffff9 (RELACOUNT)          3
0x0000000000000000 (NULL)               0x0
$
[Дополнение:] Версии и информация о системе:

Подробнее здесь: https://stackoverflow.com/questions/790 ... -prevent-t

Вернуться в «Python»