x86 bináris konvertálás MIPS binárissá

Fórumok

Adott egy USB-s DVB vevő, amihez nincs kész Linuxos driver, van viszont egy gyártó által mellékelt, patch-elt Linux TV kernel fa. Le kell fordítani, és remekül működik Ubuntu x86-on vagy x64-en.

A probléma a következő lenne. A lefordítandó forrás felhasznál olyan object fájlokat az architektúrának megfelelően, amelyeknek nincs meg a forrásuk. Le szeretném fordítani ezt az egészet cuccot MIPS-re (OpenWRT). Több megoldási lehetőségre is gondoltam, de nem tudom melyik mennyire használható:

1, Az object fájlokat decompile-olnám egy Boomerang nevű programmal, amiből C kódot kapnék, és ezt fordítabám le az object fájlok helyett. A Boomerang valamiért viszont nem tudja visszafejteni az object fájlokat, hiába adok meg egy kezdő címet, hogy honnan kezdje a decompile-olást. Csináltam egy tesztprogramot hozzá, azzal sem ment ugyanez a felállás, tehát amikor nem volt futtatható programmá linkelve. Megpróbáltam decompile-olni az object fájlokat felhasználó kernel modult, de így csak a kód egy nagyon minimális részét tudta visszafordítani.

2, A .o-kat assembly-be visszafordítani, és átírni/konvertálni az x86 ASM-et MIPS ASM-re. A manuális átírást nem tartom könnyen járható útnak, mert az objdump egy 42ezer soros ASM-et adott vissza az egyik .o-ra.

3, Valahogy közvetlenül a binárist átrakni MIPS-es binárissá, viszont nem tudom, hogy ilyen módszer egyáltalán létezik-e.

Néhány info:


# objdump -t tbsdvbcctrl.o.x86

tbsdvbcctrl.o.x86: file format elf32-i386

SYMBOL TABLE:
00000000 l df *ABS* 00000000 tbsdvbcctrl.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .debug_abbrev 00000000 .debug_abbrev
00000000 l d .debug_info 00000000 .debug_info
00000000 l d .debug_line 00000000 .debug_line
00000000 l d .debug_frame 00000000 .debug_frame
00000000 l d .debug_loc 00000000 .debug_loc
00000000 l d .debug_pubnames 00000000 .debug_pubnames
00000000 l d .debug_aranges 00000000 .debug_aranges
00000000 l d .debug_str 00000000 .debug_str
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 g F .text 0000004a tbsdvbcctrl
00000000 *UND* 00000000 usb_control_msg

# nm tbsdvbcctrl.o.x86
00000000 T tbsdvbcctrl
U usb_control_msg

Valaki, akinek volt már tapasztalata hasonlóval, tudna segíteni?

Hozzászólások

Ez nem tűnik triviálisnak, hiszen minden más. A regiszterek, az utasítások, a környezet, úgy az egésznek a működése.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szerintem full esélytelen az, amit szeretnél.

Az automatizált assembly szintű átfordításhoz (inkább reassemblyhez) az kéne, hogy a target jelentősen gyorsabb legyen, mint a forrás architektúra. Azaz pl. egy 100MHz-es CPU kódját egy 2-3GHZ-es PC-re át lehet így rakni. Egy PC-s kódot egy 100-400MHz-es MIPS-re meg nem.
A 42ezer soros assembly-t kézzel nem fogod átrakni emberi időn belül, ez gondolom nyilvánvaló.

És akkor azt a problémát is számba kell venni, hogy esetleg nem elegendő ugyanazt megcsinálni MIPS-en, mint amit az x86-os kód csinál, hanem talán szemantikailag is hozzá kell nyúlni a kódhoz (pl. x86-on van unaligned access, MIPS-en meg alapvetően nincs, tehát ha a kód ilyet használ, akkor azt át kell írni), azaz meg is kéne érteni, hogy mit csinál, és hogyan, és szükség szerint módosítani.

Felejtsd el. Nem elég ugyanazt csinálni. Más a két cucc.
Ahhoz, hogy ez menjen valahogy vissza kéne fejtened az x86-os cucc MŰKÖDÉSÉT. Nem, a kód nem elég, mert a másik cuccon sok minden lenne máshogy. Azt kell értened, hogy mit csinál és újraírni az egészet.
Nem tartom igazából lehetetlennek, de ha így kezdtél hozzá akkor szerintem neked nem fog menni.

Úgy látom, hogy assembly oldalról közelítettétek meg. Én sem tudom, hogy lehetne, hiszen ezért kérdeztem, hirtelen ez a három megoldás jött ki az ötletelésemből. Az assembly-hez nem értek, de ha vissza lehetne fejteni valahogy a kódot C-re, akkor ott miért lenne fontos, hogy big vs little endian, vagy MIPS vs x86? Ezt a fordító elintézi, nem?

És hogyan fejted vissza C-re? Mert, ha lényegében C-ben megfogalmazott, tartalmilag assembly kódod lesz, azzal szerintem nem vagy előrébb. Legjobb esetben valami olyasmit kapsz, mintha emulálnál egy x86-ot MIPS-en. Tehát lényegesen gyorsabbnak kell lennie a cél platformnak, mint ahonnan a kód származik. Azt erősen kétlem, hogy egy optimalizált gépi kódból vissza tudna alakítani egy olyan kódot, amely az eredeti szándékot fejezi ki. Tehát van sok assembly sorod, s abból csinál egyetlen C sorban lévő kifejezést, bármit. Ha assembly-ben van egy rakás shiftelés, összeadás, összehasonlítás, feltételes ugrás, abból nem igazán tudom elképzelni, hogyan lesz egy if (kifejezés) valami;, miközben gépi kódban fene tudja, ennek hol van az eleje. Az külön jó, ha netán hardware-hez is akar nyúlni ez a kernel modul.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Valami tbs tuner? Mi a pontos típusa, hardver id, device id? Ha ismert, akkor milyen chipsetes?

Vegyél másik dvb usb cuccot, olyat, amihez van megfelelő opensource driver, lehetőleg a kernelben. Sokkal kevesebbbe kerül egy ilyen cucc, mint amennyi idődet el fogod pazarolni ezzel a projekttel, ráadásul ha sikerül is, akkor sem érsz vele semmit.

Az utókornak: a problémát sikerült megoldanom, a cucc egy TBS USB 2.0-ás DVB-C vevő volt. Végülis egy debug strip után nem volt olyan hosszú a bináris, mint elsőre tűnt. Visszafejtettem C-re a frontend részt, amihez hiányzott forrás, lett kb. ezer sor, pár nap kínlódás és javítás után ment is MIPS BE-n, de legalább az assembly-hez több közöm lett, mint eddig volt. :) Később lehet írok róla egy cikket, addig is akinek erre lenne szüksége, szívesen segítek privátban.

Grat.

Ha viszfejtett kod alapjan tudnal egy specet irni, egy clean room implementaciohoz, az volna a jo..

Amit nem lehet megirni assemblyben, azt nem lehet megirni.