-
-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy path__init__.py
More file actions
133 lines (111 loc) · 4.11 KB
/
Copy path__init__.py
File metadata and controls
133 lines (111 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#
# Copyright (c) 2019 nexB Inc. and others. All rights reserved.
# http://nexb.com and https://github.com/nexB/scancode-toolkit/
# The ScanCode software is licensed under the Apache License version 2.0.
# Data generated with ScanCode require an acknowledgment.
# ScanCode is a trademark of nexB Inc.
#
# You may not use this software except in compliance with the License.
# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
# When you publish or redistribute any data created with ScanCode or any ScanCode
# derivative work, you must accompany this data with the following acknowledgment:
#
# Generated with ScanCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES
# OR CONDITIONS OF ANY KIND, either express or implied. No content created from
# ScanCode should be considered or used as legal advice. Consult an Attorney
# for any legal advice.
# ScanCode is a free software code scanning tool from nexB Inc. and others.
# Visit https://github.com/nexB/scancode-toolkit/ for support and download.
from __future__ import absolute_import
from __future__ import unicode_literals
import os
from functools import partial
from itertools import chain
import attr
from commoncode import fileutils
from plugincode.scan import ScanPlugin
from plugincode.scan import scan_impl
from scancode import CommandLineOption
from scancode import SCAN_GROUP
from typecode import contenttype
from dwarf import dwarf
from dwarf import dwarf2
@scan_impl
class DwarfScanner(ScanPlugin):
"""
Scan a dwarf infos for URLs.
"""
resource_attributes = dict(
dwarf_source_path=attr.ib(default=attr.Factory(list), repr=False))
options = [
CommandLineOption(('--dwarf',),
is_flag=True, default=False,
help='Collect source code path from compilation units found in '
'ELF DWARFs.',
help_group=SCAN_GROUP,
sort_order=100),
]
def is_enabled(self, dwarf, **kwargs):
return dwarf
def get_scanner(self, **kwargs):
return get_dwarfs
def get_dwarfs(location, **kwargs):
"""
Return a mapping with original_source_files and included_source_files or None.
"""
return dict(
dwarf_source_path=list(dwarf_source_path(location)))
def dwarf_source_path(location):
"""
Collect unique paths to compiled source code found in Elf binaries DWARF
sections for D2D.
"""
if not os.path.exists(location):
return
T = contenttype.get_type(location)
if not (T.is_elf or T.is_stripped_elf):
return
seen_paths = set()
path_file_names = set()
bare_file_names = set()
for dpath in chain(get_dwarf1(location), get_dwarf2(location)):
if dpath in seen_paths:
continue
fn = fileutils.file_name(dpath)
if fn == dpath:
bare_file_names.add(fn)
continue
else:
path_file_names.add(fn)
seen_paths.add(dpath)
yield dpath
# only yield filename that do not exist as full paths
for bfn in sorted(bare_file_names):
if bfn not in path_file_names and bfn not in seen_paths:
yield bfn
seen_paths.add(bfn)
def get_dwarf1(location):
"""
Using Dwarfdump
"""
d = dwarf.Dwarf(location)
if d:
# Show the error in the scan result ahead to make it easy to be catched
for e in d.parse_errors:
yield e
# Note: we return all paths at once, when we should probably return the
# std and original path as separate annotations
for p in d.original_source_files + d.included_source_files:
yield p
def get_dwarf2(location):
"""
Using NM
"""
for _, _, path_to_source, _ in dwarf2.get_dwarfs(location):
if path_to_source:
yield path_to_source