---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://perforator.tech/docs/en/reference/language-support/python/parse_elf.md
---
> **Documentation Index:** Fetch the complete configuration index at https://perforator.tech/docs/en/llms.txt

# ELF Parsing

## Requirements for ELF CPython binary:

* `.dynsym`, `.rodata`, `.text` sections
* `Py_Version` or `Py_GetVersion` symbol available in `.dynsym`
* `_PyThreadState_GetCurrent` or `_PyRuntime` symbol available in `.dynsym`
* `_PyGILState_Check` symbol available in `.dynsym` for CPython before 3.12

## Python Version

There are multiple ways to parse the Python version from an ELF file that we utilize in Perforator.

### `Py_Version` Symbol

There is a `Py_Version` symbol in the ELF file. This is a global variable that stores 4 bytes of the Python version: the first byte is the major version, the second byte is the minor version, the third byte is the micro version, and the fourth byte is the release level.

### Disassemble `Py_GetVersion` Function

For CPython versions earlier than 3.11, we can disassemble the `Py_GetVersion` function to get the version.

There is this line of code inside the `Py_GetVersion` function:

```
PyOS_snprintf(version, sizeof(version), buildinfo_format, PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());
```

Perforator extracts the 4th argument, which is a pointer to a constant global string with the Python version in the `.rodata` section.

Then, we can read the version as a string from this address in the binary.

## `_PyRuntime` Global Variable

There is a `_PyRuntime` symbol in the `.dynsym` section which can be used to obtain the address of the `_PyRuntime` global variable.

## Disassembling `PyThreadState_GetCurrent`

The `PyThreadState_GetCurrent` function can be disassembled to get the offset of `_PyThreadState_Current` in the Thread Local Image for [Python Thread State collection](https://perforator.tech/docs/en/reference/language-support/python/threadstate.md).
