1#!/usr/bin/env python3 2# 3# Copyright (C) 2019 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""This module contains utilities to read ELF files.""" 18 19import re 20import subprocess 21 22 23_ELF_CLASS = re.compile( 24 '\\s*Class:\\s*(.*)$') 25_DT_NEEDED = re.compile( 26 '\\s*0x[0-9a-fA-F]+\\s+\\(NEEDED\\)\\s+Shared library: \\[(.*)\\]$') 27_DT_SONAME = re.compile( 28 '\\s*0x[0-9a-fA-F]+\\s+\\(SONAME\\)\\s+Library soname: \\[(.*)\\]$') 29 30 31def readobj(path): 32 """Read ELF bitness, DT_SONAME, and DT_NEEDED.""" 33 34 # Read ELF class (32-bit / 64-bit) 35 proc = subprocess.Popen(['readelf', '-h', path], stdout=subprocess.PIPE, 36 stderr=subprocess.PIPE) 37 stdout = proc.communicate()[0] 38 is_32bit = False 39 for line in stdout.decode('utf-8').splitlines(): 40 match = _ELF_CLASS.match(line) 41 if match: 42 if match.group(1) == 'ELF32': 43 is_32bit = True 44 45 # Read DT_SONAME and DT_NEEDED 46 proc = subprocess.Popen(['readelf', '-d', path], stdout=subprocess.PIPE, 47 stderr=subprocess.PIPE) 48 stdout = proc.communicate()[0] 49 dt_soname = None 50 dt_needed = set() 51 for line in stdout.decode('utf-8').splitlines(): 52 match = _DT_NEEDED.match(line) 53 if match: 54 dt_needed.add(match.group(1)) 55 continue 56 match = _DT_SONAME.match(line) 57 if match: 58 dt_soname = match.group(1) 59 continue 60 61 return is_32bit, dt_soname, dt_needed 62