LINUX.ORG.RU

откуда берутся стеки

 , , , ,


0

2

Откуда берётся стек в программе выполняющейся без ОС (загрузчике ОС, например)? Насколько я себе представляю, его нужно создавать самому. Или есть какая-то магия gcc?

Пример из практики, код NetBSD.

int stack[8192/4 + 4] __attribute__((__aligned__ (4), __used__));

А в соседнем файле,

int devopen() {
 ...
 /* allow disk blocks up to 65536 bytes */
   char buf[65536];
Локальный массив, по стандарту, создаётся на стеке. Но стека-то столько нет. В результате, у меня buf наползает на код. И как только что-то большое записывается в buf - наступает конец. Однако, есть куча сообщений в сети, что этот код работает. Но, чёрт побери, как?

★★★★★

Пример из практики, код NetBSD.

Ссылку на исходный файл в веб-интерфейсе системы контроля версий, сестра!

Deleted
()

Откуда берётся стек в программе выполняющейся без ОС (загрузчике ОС, например)?

открывайте архитектуру PC и учите, загрузчик файла который должен работать без ОС, читает формат файла и сам устанавливает стек

anonymous
()

Обычно его задают в скриптах ld а не в коде. Так же как и области адресов для глобальных и статических переменных. А в коде надо будет указатель стека инициализировать, и gcc здесь не поможет.

amaora ★★
()
Ответ на: комментарий от amaora

Ну, я так себе это и представлял. Но почему же этот код мог хоть у кого-то работать?

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

Эм... мда.

Но почему же этот код мог хоть у кого-то работать?

Магия! Ты уверен, что у тех, у кого он работает, он не патченный?

Deleted
()
Ответ на: комментарий от alt-x

Ага, нашел уже. Не поленился исходники скачать, чтоб погрепать.

Deleted
()

Стек настраивается записью адреса базы стека в соответствующие регистры процессора. Это может делать как операционная система, так и загрузчик или любая программа, работающая с железом напрямую без ОС.

Для x86 архитектуры соответственно стек устанавливается записью нужного адреса в SS:ESP

Harald ★★★★★
()

на самом деле стека нет. есть только push, pop и регистр sp (stack pointer)

при запуске ОС выбирается произвольная область памяти, sp инициализируется в неё, и поехали.

при запуске exec ОС делает это для приложения сама, основываясь на информации в запускаемом файле. хотя приложение вправе делать с sp что угодно, и может насоздавать себе 50 стеков хоть в куче, хоть в .data

MyTrooName ★★★★★
()
Ответ на: комментарий от Deleted

Магия! Ты уверен, что у тех, у кого он работает, он не патченный?

Не на 100%, к сожалению. Другой вариант: могло случиться, что в силу каких-либо оптимизаций, gcc зарезервировал место для локальных переменных до того как стек переставили на место?

У меня просто не хватает фантазии придумать, как этот код мог работать.

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

Ну, всё-таки не совсем ядро, его загрузчик.

Это же меняет дело %) Возможно, никто не пытался запустить код в таких условиях, как ты. Или ты перенес вызов в какую-то более раннюю точку, до того, как загрузчик выделит стек побольше.

tailgunner ★★★★★
()

их программисты приносят.

anonymous
()
Ответ на: комментарий от tailgunner

Нэ перэнасил, клянусь ваще! Стоковый делает тоже самое. Если только каким-то чудом, на железке, про которую пишут, что работает, ELF загрузчика запускается с другого места, что у меня. Что нельзя, конечно, полностью исключить: разработчики объ*лись с ldscript, и то что они генерят по умолчанию не является корректным ELFом.

Но это маловероятно, прошивка той железки построена на базе той же прошивки, что и моя.

alt-x ★★★★★
() автор топика

Локальный массив, по стандарту, создаётся на стеке. Но стека-то столько нет.

Видал я таких как ты. Удивлялись чего это из-за функции типа

int somefunc(inta, intb) {
  char [255] arr;
...

контроллер со стеком 255 «глючит». Еле убедил статиком массив сделать. По моему опыту тебе объяснять бесполезно, что такое на самом деле стек и почему из-за таких как ты это бич для процессора, а?

anonymous
()
Ответ на: комментарий от alt-x

разработчики объ*лись с ldscript, и то что они генерят по умолчанию не является корректным ELFом.

Если сейчас сегменты лежат по другим адресам, это могло бы объяснить наползание стека на код.

tailgunner ★★★★★
()

возможно у других программа не заполняет buf целиком в процессе работы и потому не падает

или стек временно где-то ещё переключается

Harald ★★★★★
()
Ответ на: комментарий от anonymous

Видал я таких как ты.

Ну, таких как ты, я тоже видал. Дочитать вопрос не могут, а уже лезут поучать. В каком месте этот код мой? Разве что из моих интернетов скачан. Не знаешь, почему он мог работать, так лучше промолчи.

alt-x ★★★★★
() автор топика
Ответ на: комментарий от MyTrooName

Принципы - то одни конечно. RS/6000 примерно.

alt-x ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Хмм. objdump и gdb тот ELF не берут, а вот readelf, оказывается, берёт:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             NOTE            00020000 000080 00b394 00 WAX  0   0 16
  [ 2] .rodata           NOTE            0002b394 00b414 0017a7 00   A  0   0  4
  [ 3] .eh_frame         NOTE            0002cb3c 00cbbc 001764 00   A  0   0  4
  [ 4] .data             NOTE            0002e2a0 00e320 0001e9 00  WA  0   0  4
  [ 5] .sdata            NOTE            0002e490 00e510 00001c 00  WA  0   0  8
  [ 6] .sbss             NOTE            0002e4ac 00e52c 00004c 00  WA  0   0  4
  [ 7] .bss              NOTE            0002e4f8 00e52c 022578 00  WA  0   0  8
  [ 8] .comment          PROGBITS        00000000 00e52c 000021 01  MS  0   0  1
  [ 9] .gnu.attributes   LOOS+ffffff5    00000000 00e54d 000014 00      0   0  1
  [10] .note             NOTE            00000000 00e564 00006c 00      0   0  4
  [11] .ident            PROGBITS        00000000 00e5d0 000076 00      0   0  1
  [12] .shstrtab         STRTAB          00000000 00e646 000061 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000080 0x00020000 0x00020000 0x0e4ac 0x30a70 RWE 0x10
  NOTE           0x000080 0x00020000 0x00020000 0x30a24 0x30a68 RWE 0x10

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata .eh_frame .data .sdata 
   01     .text .rodata .eh_frame .data .sdata .sbss .comment .gnu.attributes .note .ident .shstrtab 

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type PowerPC is not currently supported.

No version information found in this file.

Notes at offset 0x00000080 with length 0x0000b394:
  Owner                 Data size       Description
  PowerPC              0x00000018       Unknown note type: (0x00001275)
  IBM,RPA-Client-Config 0x0000001c      Unknown note type: (0x12759999)
readelf: Warning: corrupt note found at offset 6c into core notes
readelf: Warning:  type: 3c200003, namesize: 7c0004ac, descsize: 4c00012c

Notes at offset 0x0000b414 with length 0x000017a7:
  Owner                 Data size       Description
readelf: Warning: corrupt note found at offset 0 into core notes
readelf: Warning:  type: 25732920, namesize: 4f465f6f, descsize: 70656e28

Notes at offset 0x0000cbbc with length 0x00001764:
  Owner                 Data size       Description
  |A
                 0x00000000     Unknown note type: (0x017a5200)
readelf: Warning: corrupt note found at offset 1c into core notes
readelf: Warning:  type: 420e10, namesize: ffff35a8, descsize: 0000003c

Notes at offset 0x0000e320 with length 0x000001e9:
  Owner                 Data size       Description
readelf: Warning: corrupt note found at offset 0 into core notes
readelf: Warning:  type: 0, namesize: 0002b520, descsize: 00000000

Notes at offset 0x0000e510 with length 0x0000001c:
  Owner                 Data size       Description
readelf: Warning: corrupt note found at offset 0 into core notes
readelf: Warning:  type: 400, namesize: 0002b498, descsize: 00000001

Notes at offset 0x0000e52c with length 0x0000004c:
  Owner                 Data size       Description
readelf: Warning: corrupt note found at offset 0 into core notes
readelf: Warning:  type: 74425344, namesize: 4743433a, descsize: 20284e65
readelf: Error: Unable to read in 0x22578 bytes of notes

Notes at offset 0x0000e564 with length 0x0000006c:
  Owner                 Data size       Description
  PowerPC              0x00000018       Unknown note type: (0x00001275)
  IBM,RPA-Client-Config 0x0000001c      Unknown note type: (0x12759999)

Но, на первый взгляд, между .data и .text 64К поместиться всё равно никак не могут.

Кстати, я правильно понимаю, что для .text в этом случае флаг W вреден? По идее, без него падало хотябы до того как начать чудачить.

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

Но, на первый взгляд, между .data и .text 64К поместиться всё равно никак не могут.

Как сказали выше - может быть, в buf ничего большого никто не писал.

Кстати, я правильно понимаю, что для .text в этом случае флаг W вреден?

Я думаю, что используемый огрызок ELF-загрузчика игнорирует этот флаг :) Но да, защищенный от записи код был бы полезен.

tailgunner ★★★★★
()

Найди примеры программирования микроконтроллеров STM32. Там крайне наглядно видно, откуда берется стек. Это просто область памяти, выделенная под эти нужды. Компилятор и линкер должны знать, где она начинается.

http://www.triplespark.net/elec/pdev/arm/stm32.html

Deleted
()
Ответ на: комментарий от tailgunner

Как сказали выше - может быть, в buf ничего большого никто не писал.

Только если IBM сильно модифицировали прошивку на B50. Во всех версиях OFW, которые я видел, до того как писать в буфер, его чистят по всей длине.

У тебя нет какой-нибудь IBM'овской машинки с OFW?

alt-x ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Пример, конечно, хороший, но из него не понятно, откуда может взяться место на стеке, если попросили больше чем создали.

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

Если попросили больше, чем создали, то будет переполнение стека. В указанном примере стек попортит остальную часть памяти. Но можно сделать так, чтобы край стека смещался к границе RAM. Тогда переполнение стека даст вам особый вид прерырания - hard fault. Вызовется соответствующая функция, и вы хотя бы об этом узнаете.

Deleted
()
Ответ на: комментарий от alt-x

Но почему же этот код мог хоть у кого-то работать?

Может, эта функция вызывается из какого-то другого контекста, и у нее банально другой стек?

Deleted
()
Ответ на: комментарий от alt-x

У тебя нет какой-нибудь IBM'овской машинки с OFW?

Нет. Я работал со встроенными вариантами PowerPC.

А почему тупо не увеличить стек?

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

А почему тупо не увеличить стек?

Если его увеличить, всё будет работать, не вопрос. Но мне не нужна NetBSD сама по себе. Я им вчера отчёт накатал, пусть исправляют, если хотят.

Она мне важна только в качестве Test Case: на IBM B50 этот код работает, на Pegasos II - тоже, а у меня - нет. Мне интересно, если на моей прошивке не работает этот поломаный код, может и какой-то целый не будет работать. Может, в прошивках B50 и Pegasos II загрузка идёт вообще по другому, и стек устанавливается не NetBSD, а OFW. А если оно и на тех машинках работает только чудом и в полнолуние, то и ладно.

alt-x ★★★★★
() автор топика
Ответ на: комментарий от alt-x

На Pegasos II чуда всё-таки нет: там оказывается совсем другая прошивка - SmartFirmware, они не чистят буфер до того как туда писать, и соответственно проблема незаметна. Может и в IBM B50 прошивка не на OFW основана. Не смог найти в сети логов, где кто-нибудь делает что-то сложнее чем setenv & boot, так что может и IBM'овцы свой велосипед запилили.

Так что, для начала вопрос снимается. Стеки не берутся.

alt-x ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.