|
22 | 22 | * ============================================================================ */ |
23 | 23 |
|
24 | 24 | /* File structure sizes */ |
25 | | -#define FILE_HEADER_PLACEHOLDER_SIZE 64 /* Placeholder written at file start */ |
26 | | -#define FILE_HEADER_SIZE 52 /* Actual header content size */ |
27 | | -#define FILE_FOOTER_SIZE 32 /* Footer size */ |
| 25 | +#define FILE_FOOTER_SIZE 32 |
28 | 26 | #define MIN_DECOMPRESS_BUFFER_SIZE (64 * 1024) /* Minimum decompression buffer */ |
29 | 27 |
|
30 | 28 | /* Progress callback frequency */ |
@@ -57,17 +55,35 @@ reader_parse_header(BinaryReader *reader, const uint8_t *data, size_t file_size) |
57 | 55 | } |
58 | 56 |
|
59 | 57 | if (version != BINARY_FORMAT_VERSION) { |
60 | | - PyErr_Format(PyExc_ValueError, "Unsupported version: %u", version); |
| 58 | + if (version > BINARY_FORMAT_VERSION && file_size >= HDR_OFF_PY_MICRO + 1) { |
| 59 | + /* Newer format - try to read Python version for better error */ |
| 60 | + uint8_t py_major = data[HDR_OFF_PY_MAJOR]; |
| 61 | + uint8_t py_minor = data[HDR_OFF_PY_MINOR]; |
| 62 | + uint8_t py_micro = data[HDR_OFF_PY_MICRO]; |
| 63 | + PyErr_Format(PyExc_ValueError, |
| 64 | + "Binary file was created with Python %u.%u.%u (format version %u), " |
| 65 | + "but this is Python %d.%d.%d (format version %d)", |
| 66 | + py_major, py_minor, py_micro, version, |
| 67 | + PY_MAJOR_VERSION, PY_MINOR_VERSION, PY_MICRO_VERSION, |
| 68 | + BINARY_FORMAT_VERSION); |
| 69 | + } else { |
| 70 | + PyErr_Format(PyExc_ValueError, |
| 71 | + "Unsupported format version %u (this reader supports version %d)", |
| 72 | + version, BINARY_FORMAT_VERSION); |
| 73 | + } |
61 | 74 | return -1; |
62 | 75 | } |
63 | 76 |
|
64 | | - memcpy(&reader->start_time_us, &data[8], sizeof(reader->start_time_us)); |
65 | | - memcpy(&reader->sample_interval_us, &data[16], sizeof(reader->sample_interval_us)); |
66 | | - memcpy(&reader->sample_count, &data[24], sizeof(reader->sample_count)); |
67 | | - memcpy(&reader->thread_count, &data[28], sizeof(reader->thread_count)); |
68 | | - memcpy(&reader->string_table_offset, &data[32], sizeof(reader->string_table_offset)); |
69 | | - memcpy(&reader->frame_table_offset, &data[40], sizeof(reader->frame_table_offset)); |
70 | | - memcpy(&reader->compression_type, &data[48], sizeof(reader->compression_type)); |
| 77 | + reader->py_major = data[HDR_OFF_PY_MAJOR]; |
| 78 | + reader->py_minor = data[HDR_OFF_PY_MINOR]; |
| 79 | + reader->py_micro = data[HDR_OFF_PY_MICRO]; |
| 80 | + memcpy(&reader->start_time_us, &data[HDR_OFF_START_TIME], HDR_SIZE_START_TIME); |
| 81 | + memcpy(&reader->sample_interval_us, &data[HDR_OFF_INTERVAL], HDR_SIZE_INTERVAL); |
| 82 | + memcpy(&reader->sample_count, &data[HDR_OFF_SAMPLES], HDR_SIZE_SAMPLES); |
| 83 | + memcpy(&reader->thread_count, &data[HDR_OFF_THREADS], HDR_SIZE_THREADS); |
| 84 | + memcpy(&reader->string_table_offset, &data[HDR_OFF_STR_TABLE], HDR_SIZE_STR_TABLE); |
| 85 | + memcpy(&reader->frame_table_offset, &data[HDR_OFF_FRAME_TABLE], HDR_SIZE_FRAME_TABLE); |
| 86 | + memcpy(&reader->compression_type, &data[HDR_OFF_COMPRESSION], HDR_SIZE_COMPRESSION); |
71 | 87 |
|
72 | 88 | return 0; |
73 | 89 | } |
@@ -1023,9 +1039,15 @@ binary_reader_replay(BinaryReader *reader, PyObject *collector, PyObject *progre |
1023 | 1039 | PyObject * |
1024 | 1040 | binary_reader_get_info(BinaryReader *reader) |
1025 | 1041 | { |
| 1042 | + PyObject *py_version = Py_BuildValue("(B,B,B)", |
| 1043 | + reader->py_major, reader->py_minor, reader->py_micro); |
| 1044 | + if (py_version == NULL) { |
| 1045 | + return NULL; |
| 1046 | + } |
1026 | 1047 | return Py_BuildValue( |
1027 | | - "{s:I, s:K, s:K, s:I, s:I, s:I, s:I, s:i}", |
| 1048 | + "{s:I, s:N, s:K, s:K, s:I, s:I, s:I, s:I, s:i}", |
1028 | 1049 | "version", BINARY_FORMAT_VERSION, |
| 1050 | + "python_version", py_version, |
1029 | 1051 | "start_time_us", reader->start_time_us, |
1030 | 1052 | "sample_interval_us", reader->sample_interval_us, |
1031 | 1053 | "sample_count", reader->sample_count, |
|
0 commit comments