Есть глючная прога работы с оборудование, без него не запускается и работать не будет чтоб проверить. Предположительно вылетает молча из-за переполнения буфера, если задать слишком большой диапазон сканирования. Прога написана на borland C++ 5.0 вроде в 200х лохматом году. В ней есть локальный массив LastMeasStr, который нужно увеличить в 128 раз или больше. Массив локальный для функции, которая хрен пойми где вызывается, есть только смещение. Как безболезненно увеличить размер массива и стека под него? Чет я забыл как там стек выделяется в exe. Начало функции типа такое: Обращение к массиву так происходит: где И в функции везде подобные вызовы, фиг поймешь как он esp сдвигает под все переменные функции:
Резервный размер стека установить в параметрах пе. Затем пофиксить число выделяемых страниц(0x85). Прежде наверно нужно посмотреть допустимый размер стека, иначе не пройдёт создание процесса(bad pe format..).
Не слишком ли много непонятного? Если прога вылетает - значит, запускается. Значит, отладчик в помощь, выясняйте конкретную причину вылета. Без неё будет тыканье вслепую с минимальными шансами угадать.
Прога запускается только вместе с устройством. Запустить ее до этой функции без устройства очень сложно. Отлаживать на работающем устройстве опасно, может сдохнуть, оно и так пищит и плачет при вылете проги. --- Сообщение объединено, 22 окт 2024 --- Точно, чет я сразу цикл выделения стека не заметил. А где прописан допустимый размер стека? В PE? И расширенный массив уже в конце стека добавлять и работать с ним, чтоб ниче не сдвигать?
В заголовке PE https://learn.microsoft.com/en-us/w...nal-header-windows-specific-fields-image-only SizeOfStackCommit/SizeOfHeapReserve
SizeOfStackReserve/SizeOfStackCommit: The maximum value for SizeOfStackReserve is 4 GB for PE32 and 16 EB (exabytes) for PE32+
CyberRSR Да, так как размер массива ограничен переменными и что бы не фиксить их смещения, лучше пофиксить смещение массива LastMeastStr.
ого планка.. это где было видано, чтобы под стек выделялось всё доступное ап? и вообще из 64-бит десктопные ос используют всего 48, а это 256 тера, по 128 юзеру и кернелу. поэтому ре может и унести столько, а вот ос наврядли.
а че, Самс уже сделал 1 ТБ планку памяти можна и побуянить )) https://semiconductor.samsung.com/d...s, TSV,with scalability for future innovation.
Так там SizeOfStackCommit всего 0x2000, явно меньше, чем в этой функции выделяется, из-за этого не может вылетать? Или я чего-то не понимаю? "The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached." В итоге весь Reserve доступен или только Commit? Чет первый раз с таким сталкиваюсь, всегда думал что ограничено Reserve. И в PE особо никогда не заглядывал.
Значит так. Для каждой нити/ветви/thread система резервирует SizeOfStackReserve блок адресов. А вот выделяет она сразу только SizeOfStackCommit страниц памяти для размещения стека. Когда указатель стека пересекает границу выделенного блока памяти (т.е. размер стека превышает SizeOfStackCommit), тогда выделяется еще одна страница памяти, но не более чем SizeOfStackReserve (одна страница это 4 кб). При этом перепрыгнуть эту страницу памяти нельзя. Т.е. если вы хотите выделить единовременно в стеке больше 4 Кб, тогда вам надо двигать указатель стека постранично и производить хотя бы одну попытку записи на новую страницу памяти, чтобы произошло срабатывание ловушки и была выделена страница памяти. При этом под наблюдением находятся только адреса ближайшей страницы памяти, а не всего диапазона (SizeOfStackReserve - SizeOfStackCommit). Обратно страницы памяти стека высвобождаются только при уничтожении нити/ветви/thread.
Короче, делаем SizeOfStackCommit = SizeOfStackReserve и не паримся, а иначе я не представляю как перенести новую переменную и подправить для нее просто адреса везде, при этом не прыгая по страницам? ААА, все я допер зачем там цикл с выделением 85 страниц.
Помимо лимитов в РЕ-заголовке, система сама выделяет лимиты для каждого из тредов потока - они прописаны в ТЕВ. Код (Text): 0:000> !teb TEB at 000007fffffde000 StackBase: 0000000000070000 StackLimit: 000000000006d000 Тогда получаем размер стека на входе 0x70000-0x6d000=0x3000 или 12K. Можно проверить атрибуты данного региона, и эти 3 страницы будут полностью доступны в любой момент: Код (Text): 0:000> !address 6d000 Usage: Stack Allocation Base: 00000000`00030000 Base Address: 00000000`0006d000 End Address: 00000000`00070000 Region Size: 00000000`00003000 <-----// Type: 00020000 MEM_PRIVATE State: 00001000 MEM_COMMIT Protect: 00000004 PAGE_READWRITE <-----// А вот сл.страница (выше текущего лимита 6d000) уже имеет атрибут сторожевой Guard. Диспетчер исключений имеет обработчик на #PG, так-что выход за пределы трёх страниц проходит безболезненно, и для этого не нужно ничего записывать в стек - просто sub rsp,3000h и всё: Код (Text): 0:000> !address 6c000 Usage: Stack Allocation Base: 00000000`00030000 Base Address: 00000000`0006b000 End Address: 00000000`0006d000 Region Size: 00000000`00002000 Type: 00020000 MEM_PRIVATE State: 00001000 MEM_COMMIT Protect: 00000104 PAGE_READWRITE | PAGE_GUARD <----// Только после первого #PG система будет выделять по одной странице, вставляя на границах сторожевые - здесь уже нужна запись в стек, иначе #AV. Если посмотреть на предыдущий блок !address, то необрабатываемое исключение "StackOverflow" получим только выше адреса AllocationBase=0x30000. Тогда получается, что моя Win7-x64 выделяет глобальный лимит для стека одного потока 70000-30000=40000h, или 256K, хотя в доках пишут 1Mb (возможно на Win10). Регион выше этого адреса уже лежит в резерве (а не commit), и его нужно выделять через VirtuaAlloc(). Код (Text): 0:000> !address 30000 Usage: Stack Allocation Base: 00000000`00030000 Base Address: 00000000`00030000 End Address: 00000000`0006b000 Region Size: 00000000`0003b000 Type: 00020000 MEM_PRIVATE State: 00002000 MEM_RESERVE <----// Protect: 00000000 Вот код, который выводит инфу о стеке из TEB, после чего выделяет в нём сразу текущий размер. Далее вплоть до 0x30000 нужно чё-нить ложить в стек, чтобы код начал пожирать его. Спойлер: StackInfo Код (ASM): format pe64 console 5.0 include 'win64ax.inc' entry start ;//----------- .data stackSize dq 0 ;//----------- section '.text' code readable executable start: sub rsp,8 mov rax,[gs:60h] ; PEB addr mov rax,[rax+10h] ; ImageBase mov ebx,[eax+3ch] ; add eax,ebx ; PE header mov r10,[rax+60h] ; StackReserved mov r11,[rax+68h] ; StackCommit cinvoke printf,<10,' PE info ========',\ 10,' Stack Reserved: 0x%08llx',\ 10,' Stack Commit..: 0x%08llx',10,0>,r10,r11 ;------------- mov rax,[gs:08h] ; StackBase mov rbx,[gs:10h] ; StackLimit mov r10,rax sub r10,rbx ; StackSize mov [stackSize],r10 shr r10,10 ; ....Kbyte mov r11,r10 shr r11,2 ; ....Pages cinvoke printf,<10,' System info ====',\ 10,' Stack Limit...: 0x%08llx',\ 10,' Stack Rsp.....: 0x%08llx',\ 10,' Stack Base....: 0x%08llx',\ 10,' Stack Size....: 0x%08llx = %d Kb = %d pages',10,0>,\ rbx,rsp,rax,[stackSize],r10,r11 ;------------- sub rsp,[stackSize] sub rsp,1000h ; call @f ; для сл.страниц нужна уже запись в стек, ;@@: sub rsp,1000h ; ...иначе #AV call @f ;<----- Обновить записи в ТЕВ @@: mov rax,[gs:08h] ; StackBase mov rbx,[gs:10h] ; StackLimit mov r10,rax sub r10,rbx ; StackSize mov [stackSize],r10 shr r10,10 ; ....Kbyte mov r11,r10 shr r11,2 ; ....Pages cinvoke printf,<10,' sub rsp,[stackSize] <------',\ 10,' sub rsp,1000h',10,\ 10,' System info ====',\ 10,' Stack Limit...: 0x%08llx',\ 10,' Stack Rsp.....: 0x%08llx',\ 10,' Stack Base....: 0x%08llx',\ 10,' Stack Size....: 0x%08llx = %d Kb = %d pages',10,0>,\ rbx,rsp,rax,[stackSize],r10,r11 @exit: cinvoke _getch cinvoke exit, 0 ;//----------- section '.idata' import data readable library msvcrt,'msvcrt.dll' include 'api\msvcrt.inc' Ради интереса я увеличил в РЕ-хидере лимит/комит в 16 раз (с дефолтных 0x1000 на 0x10000), и получил такую картину: