Skip to content

Commit 0127496

Browse files
committed
more ELF information, info duplication fixed
1 parent 0fe1087 commit 0127496

File tree

3 files changed

+68
-26
lines changed

3 files changed

+68
-26
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ A simple tool for viewing OpenDingux and RetroFW packages. It supports opening O
55
=== to do list ===
66
- support for multiple open files (multitab view, cmdline)
77
- image viewer navigation in case of multiple images in the root directory
8-
- avoid duplication of content of manual files (and possibly other files) via a reference to another section in the OPK description
98
- windows port
109
- maybe C++ port
11-
- maybe more information about ELF files
10+
- extract OPK

layout.glade

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,11 @@ DAMAGES.
474474
</object>
475475
</child>
476476
</object>
477+
<object class="GtkImage" id="image2">
478+
<property name="visible">True</property>
479+
<property name="can-focus">False</property>
480+
<property name="stock">gtk-execute</property>
481+
</object>
477482
<object class="GtkWindow" id="window1">
478483
<property name="can-focus">False</property>
479484
<property name="default-width">480</property>
@@ -507,6 +512,16 @@ DAMAGES.
507512
<signal name="activate" handler="onOpen" swapped="no"/>
508513
</object>
509514
</child>
515+
<child>
516+
<object class="GtkImageMenuItem" id="imagemenuitem1">
517+
<property name="label">Extract</property>
518+
<property name="visible">True</property>
519+
<property name="can-focus">False</property>
520+
<property name="image">image2</property>
521+
<property name="use-stock">False</property>
522+
<signal name="activate" handler="onExtract" swapped="no"/>
523+
</object>
524+
</child>
510525
<child>
511526
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
512527
<property name="visible">True</property>

opkview.py

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import tempfile
77
import os
88
import magic
9+
import io
10+
from elftools.elf.elffile import ELFFile
911
from PySquashfsImage import SquashFsImage
1012
import gi
1113
gi.require_version("Gtk", "3.0")
@@ -43,20 +45,16 @@ def load_opk(path):
4345
desktopfile.read_string(i.getContent().decode("utf-8"))
4446
dset = dict()
4547
dset['appname'] = desktopfile["Desktop Entry"].get("Name", "", raw=True)
46-
dset['executable'] = os.path.basename(desktopfile["Desktop Entry"].get("Exec", "<none>", raw=True).split()[0])
47-
if dset['executable'] in execs:
48-
execs[dset['executable']].add(iname)
48+
dset['executable'] = os.path.basename(desktopfile["Desktop Entry"].get("Exec", "", raw=True).split()[0])
49+
if dset['executable'] != "":
50+
execs[dset['executable']] = dict()
4951
else:
50-
execs[dset['executable']] = {iname}
51-
dset['execid'] = ""
52+
dset['executable'] = "<none>"
5253
dset['version'] = desktopfile["Desktop Entry"].get("Version", "", raw=True)
5354
dset['comment'] = desktopfile["Desktop Entry"].get("Comment", "", raw=True)
5455
dset['manualpath'] = desktopfile["Desktop Entry"].get("X-OD-Manual", "", raw=True)
55-
if dset['manualpath'] in manuals:
56-
manuals[dset['manualpath']].add(iname)
57-
else:
58-
manuals[dset['manualpath']] = {iname}
59-
dset['manual'] = ""
56+
if dset['manualpath'] != "":
57+
manuals[dset['manualpath']] = ""
6058
desktops[iname] = dset
6159
platformset.add(m.group(1))
6260
m = re.match(r".+\.png", iname)
@@ -78,20 +76,24 @@ def load_opk(path):
7876
man = ""
7977
for e in encodings:
8078
try:
81-
man = i.getContent().decode(e)
79+
manuals[iname] = i.getContent().decode(e)
8280
break
8381
except:
84-
man = "<reading error>"
85-
for m in manuals[iname]:
86-
desktops[m]['manual'] = man
82+
manuals[iname] = "<reading error>"
8783
if iname in execs:
88-
ei = magic.from_buffer(i.getContent())
89-
for e in execs[iname]:
90-
desktops[e]['execid'] = ei
91-
# workaround for libmagic from_file vs from_buffer bug for elves
92-
#with tempfile.NamedTemporaryFile() as f:
93-
# f.write(i.getContent())
94-
# execid = magic.from_file(f.name)
84+
execs[iname]['magic'] = magic.from_buffer(i.getContent())
85+
execs[iname]['mime'] = magic.from_buffer(i.getContent(), mime=True)
86+
execs[iname]['iself'] = execs[iname]['mime'] == 'application/x-executable' or execs[iname]['mime'] == 'application/x-pie-executable'
87+
if execs[iname]['iself']:
88+
bstream = io.BytesIO(i.getContent())
89+
elf = ELFFile(bstream)
90+
dynsec = elf.get_section_by_name(".dynamic")
91+
execs[iname]['dynamic'] = dynsec is not None
92+
if execs[iname]['dynamic']:
93+
execs[iname]['deps'] = []
94+
for tag in dynsec.iter_tags():
95+
if tag.entry.d_tag == "DT_NEEDED":
96+
execs[iname]['deps'].append(tag.needed)
9597
opk.close()
9698
if platforms == "":
9799
platforms = "none"
@@ -104,14 +106,37 @@ def load_opk(path):
104106
desktops[key]['appname'] = "none"
105107
content += "Appname: " + desktops[key]['appname'] + "\n"
106108
content += "Executable: " + desktops[key]['executable'] + "\n"
107-
content += "Exec identity: " + desktops[key]['execid'] + "\n"
108109
if desktops[key]['version'] != "":
109110
content += "Version: " + desktops[key]['version'] + "\n"
110111
if desktops[key]['comment'] != "":
111112
content += "Comment: " + desktops[key]['comment'] + "\n"
112-
if desktops[key]['manual'] != "":
113-
content += "Manual:\n" + desktops[key]['manual'] + "\n"
113+
if desktops[key]['manualpath'] != "":
114+
content += "Manual: " + desktops[key]['manualpath'] + "\n"
115+
content += "\n"
116+
for key in execs:
117+
content += "Executable " + key + "\n"
118+
content += "Identity: " + execs[key]['magic'] + "\n"
119+
if execs[key]['iself']:
120+
if execs[key]['dynamic']:
121+
content += "The executable is dynamically linked.\n"
122+
if len(execs[key]['deps']) == 0:
123+
content += "No dynamic dependencies detected.\n"
124+
else:
125+
content += "Dynamic dependencies:\n"
126+
for d in execs[key]['deps']:
127+
content += " " + d + "\n"
128+
else:
129+
content += "The executable is statically linked.\n"
114130
content += "\n"
131+
for key in manuals:
132+
if manuals[key] == "":
133+
content += "Manual " + key + " is empty or nonexistent.\n"
134+
else:
135+
content += "Manual " + key + "\n"
136+
content += "=== MANUAL START ===\n"
137+
content += manuals[key] + "\n"
138+
content += "=== MANUAL END ===\n"
139+
content += "\n"
115140
textbuffer.set_text(content)
116141

117142
class Handler:
@@ -129,6 +154,9 @@ def onOpen(self, *args):
129154
load_opk(filepath)
130155
dialog.destroy()
131156

157+
def onExtract(self, *args):
158+
print("Extract clicked")
159+
132160
def onAbout(self, *args):
133161
aboutdialog.show()
134162

0 commit comments

Comments
 (0)