PageRenderTime 78ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/bionic/libc/tools/bionic_utils.py

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
Python | 378 lines | 361 code | 10 blank | 7 comment | 9 complexity | 27ba292777f2f38365ec646d7e8540ae MD5 | raw file
  1. # common python utility routines for the Bionic tool scripts
  2. import sys, os, commands, string
  3. # support Bionic architectures, add new ones as appropriate
  4. #
  5. bionic_archs = [ "arm", "x86", "mips" ]
  6. # basic debugging trace support
  7. # call D_setlevel to set the verbosity level
  8. # and D(), D2(), D3(), D4() to add traces
  9. #
  10. verbose = 0
  11. def D(msg):
  12. global verbose
  13. if verbose > 0:
  14. print msg
  15. def D2(msg):
  16. global verbose
  17. if verbose >= 2:
  18. print msg
  19. def D3(msg):
  20. global verbose
  21. if verbose >= 3:
  22. print msg
  23. def D4(msg):
  24. global verbose
  25. if verbose >= 4:
  26. print msg
  27. def D_setlevel(level):
  28. global verbose
  29. verbose = level
  30. def find_dir_of(path):
  31. '''return the directory name of 'path', or "." if there is none'''
  32. # remove trailing slash
  33. if len(path) > 1 and path[-1] == '/':
  34. path = path[:-1]
  35. # find parent directory name
  36. d = os.path.dirname(path)
  37. if d == "":
  38. return "."
  39. else:
  40. return d
  41. # other stuff
  42. #
  43. #
  44. def find_file_from_upwards(from_path,target_file):
  45. """find a file in the current directory or its parents. if 'from_path' is None,
  46. seach from the current program's directory"""
  47. path = from_path
  48. if path == None:
  49. path = find_dir_of(sys.argv[0])
  50. D("this script seems to be located in: %s" % path)
  51. while 1:
  52. if path == "":
  53. path = "."
  54. file = path + "/" + target_file
  55. D("probing "+file)
  56. if os.path.isfile(file):
  57. D("found %s in %s" % (target_file, path))
  58. return file
  59. if path == ".":
  60. break
  61. path = os.path.dirname(path)
  62. path = ""
  63. while 1:
  64. path = "../" + path
  65. file = path + target_file
  66. D("probing "+file)
  67. if os.path.isfile(file):
  68. D("found %s in %s" % (target_file, path))
  69. return file
  70. return None
  71. def find_bionic_root():
  72. '''find the root of the Bionic source tree. we check for the SYSCALLS.TXT file
  73. from the location of the current program's directory.'''
  74. # note that we can't use find_file_from_upwards() since we can't use os.path.abspath
  75. # that's because in some cases the p4 client is in a symlinked directory, and this
  76. # function will return the real path instead, which later creates problems when
  77. # p4 commands are issued
  78. #
  79. file = find_file_from_upwards(None, "SYSCALLS.TXT")
  80. if file:
  81. return os.path.dirname(file)
  82. else:
  83. return None
  84. def find_original_kernel_headers():
  85. """try to find the directory containing the original kernel headers"""
  86. bionic_root = find_bionic_root()
  87. if not bionic_root:
  88. D("Could not find Bionic root !!")
  89. return None
  90. path = os.path.normpath(bionic_root + "/../../external/kernel-headers/original")
  91. if not os.path.isdir(path):
  92. D("Could not find %s" % (path))
  93. return None
  94. return path
  95. def find_kernel_headers():
  96. """try to find the directory containing the kernel headers for this machine"""
  97. # First try to find the original kernel headers.
  98. ret = find_original_kernel_headers()
  99. if ret:
  100. D("found original kernel headers in: %s" % (ret))
  101. return ret
  102. status, version = commands.getstatusoutput( "uname -r" ) # get Linux kernel version
  103. if status != 0:
  104. D("could not execute 'uname -r' command properly")
  105. return None
  106. # get rid of the "-xenU" suffix that is found in Xen virtual machines
  107. if len(version) > 5 and version[-5:] == "-xenU":
  108. version = version[:-5]
  109. path = "/usr/src/linux-headers-" + version + "/include"
  110. D("probing %s for kernel headers" % (path))
  111. ret = os.path.isdir( path )
  112. if ret:
  113. D("found kernel headers in: %s" % (path))
  114. return path
  115. return None
  116. def find_arch_header(kernel_headers,arch,header):
  117. # First, try in <root>/arch/<arm>/include/<header>
  118. # corresponding to the location in the kernel source tree for
  119. # certain architectures (e.g. arm).
  120. path = "%s/arch/%s/include/asm/%s" % (kernel_headers, arch, header)
  121. D("Probing for %s" % path)
  122. if os.path.exists(path):
  123. return path
  124. # Try <root>/asm-<arch>/include/<header> corresponding to the location
  125. # in the kernel source tree for other architectures (e.g. x86).
  126. path = "%s/include/asm-%s/%s" % (kernel_headers, arch, header)
  127. D("Probing for %s" % path)
  128. if os.path.exists(path):
  129. return path
  130. # Otherwise, look under <root>/asm-<arch>/<header> corresponding
  131. # the original kernel headers directory
  132. path = "%s/asm-%s/%s" % (kernel_headers, arch, header)
  133. D("Probing for %s" % path)
  134. if os.path.exists(path):
  135. return path
  136. return None
  137. # parser for the SYSCALLS.TXT file
  138. #
  139. class SysCallsTxtParser:
  140. def __init__(self):
  141. self.syscalls = []
  142. self.lineno = 0
  143. def E(self, msg):
  144. print "%d: %s" % (self.lineno, msg)
  145. def parse_line(self, line):
  146. """ parse a syscall spec line.
  147. line processing, format is
  148. return type func_name[:syscall_name[:call_id]] ( [paramlist] ) (syscall_number[,syscall_number_x86])|stub
  149. """
  150. pos_lparen = line.find('(')
  151. E = self.E
  152. if pos_lparen < 0:
  153. E("missing left parenthesis in '%s'" % line)
  154. return
  155. pos_rparen = line.rfind(')')
  156. if pos_rparen < 0 or pos_rparen <= pos_lparen:
  157. E("missing or misplaced right parenthesis in '%s'" % line)
  158. return
  159. return_type = line[:pos_lparen].strip().split()
  160. if len(return_type) < 2:
  161. E("missing return type in '%s'" % line)
  162. return
  163. syscall_func = return_type[-1]
  164. return_type = string.join(return_type[:-1],' ')
  165. call_id = -1
  166. pos_colon = syscall_func.find(':')
  167. if pos_colon < 0:
  168. syscall_name = syscall_func
  169. else:
  170. if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
  171. E("misplaced colon in '%s'" % line)
  172. return
  173. # now find if there is a call_id for a dispatch-type syscall
  174. # after the optional 2nd colon
  175. pos_colon2 = syscall_func.find(':', pos_colon + 1)
  176. if pos_colon2 < 0:
  177. syscall_name = syscall_func[pos_colon+1:]
  178. syscall_func = syscall_func[:pos_colon]
  179. else:
  180. if pos_colon2+1 >= len(syscall_func):
  181. E("misplaced colon2 in '%s'" % line)
  182. return
  183. syscall_name = syscall_func[(pos_colon+1):pos_colon2]
  184. call_id = int(syscall_func[pos_colon2+1:])
  185. syscall_func = syscall_func[:pos_colon]
  186. if pos_rparen > pos_lparen+1:
  187. syscall_params = line[pos_lparen+1:pos_rparen].split(',')
  188. params = string.join(syscall_params,',')
  189. else:
  190. syscall_params = []
  191. params = "void"
  192. number = line[pos_rparen+1:].strip()
  193. if number == "stub":
  194. syscall_common = -1
  195. syscall_arm = -1
  196. syscall_x86 = -1
  197. syscall_mips = -1
  198. else:
  199. try:
  200. if number[0] == '#':
  201. number = number[1:].strip()
  202. numbers = string.split(number,',')
  203. if len(numbers) == 1:
  204. syscall_common = int(numbers[0])
  205. syscall_arm = -1
  206. syscall_x86 = -1
  207. syscall_mips = -1
  208. else:
  209. if len(numbers) == 3:
  210. syscall_common = -1
  211. syscall_arm = int(numbers[0])
  212. syscall_x86 = int(numbers[1])
  213. syscall_mips = int(numbers[2])
  214. else:
  215. E("invalid syscall number format in '%s'" % line)
  216. return
  217. except:
  218. E("invalid syscall number in '%s'" % line)
  219. return
  220. global verbose
  221. if verbose >= 2:
  222. if call_id == -1:
  223. if syscall_common == -1:
  224. print "%s: %d,%d,%d" % (syscall_name, syscall_arm, syscall_x86, syscall_mips)
  225. else:
  226. print "%s: %d" % (syscall_name, syscall_common)
  227. else:
  228. if syscall_common == -1:
  229. print "%s(%d): %d,%d,%d" % (syscall_name, call_id, syscall_arm, syscall_x86, syscall_mips)
  230. else:
  231. print "%s(%d): %d" % (syscall_name, call_id, syscall_common)
  232. t = { "armid" : syscall_arm,
  233. "x86id" : syscall_x86,
  234. "mipsid" : syscall_mips,
  235. "common" : syscall_common,
  236. "cid" : call_id,
  237. "name" : syscall_name,
  238. "func" : syscall_func,
  239. "params" : syscall_params,
  240. "decl" : "%-15s %s (%s);" % (return_type, syscall_func, params) }
  241. self.syscalls.append(t)
  242. def parse_file(self, file_path):
  243. D2("parse_file: %s" % file_path)
  244. fp = open(file_path)
  245. for line in fp.xreadlines():
  246. self.lineno += 1
  247. line = line.strip()
  248. if not line: continue
  249. if line[0] == '#': continue
  250. self.parse_line(line)
  251. fp.close()
  252. class Output:
  253. def __init__(self,out=sys.stdout):
  254. self.out = out
  255. def write(self,msg):
  256. self.out.write(msg)
  257. def writeln(self,msg):
  258. self.out.write(msg)
  259. self.out.write("\n")
  260. class StringOutput:
  261. def __init__(self):
  262. self.line = ""
  263. def write(self,msg):
  264. self.line += msg
  265. D2("write '%s'" % msg)
  266. def writeln(self,msg):
  267. self.line += msg + '\n'
  268. D2("write '%s\\n'"% msg)
  269. def get(self):
  270. return self.line
  271. def create_file_path(path):
  272. dirs = []
  273. while 1:
  274. parent = os.path.dirname(path)
  275. if parent == "/":
  276. break
  277. dirs.append(parent)
  278. path = parent
  279. dirs.reverse()
  280. for dir in dirs:
  281. #print "dir %s" % dir
  282. if os.path.isdir(dir):
  283. continue
  284. os.mkdir(dir)
  285. def walk_source_files(paths,callback,args,excludes=[]):
  286. """recursively walk a list of paths and files, only keeping the source files in directories"""
  287. for path in paths:
  288. if not os.path.isdir(path):
  289. callback(path,args)
  290. else:
  291. for root, dirs, files in os.walk(path):
  292. #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
  293. if len(excludes):
  294. for d in dirs[:]:
  295. if d in excludes:
  296. dirs.remove(d)
  297. for f in files:
  298. r, ext = os.path.splitext(f)
  299. if ext in [ ".h", ".c", ".cpp", ".S" ]:
  300. callback( "%s/%s" % (root,f), args )
  301. def cleanup_dir(path):
  302. """create a directory if needed, and ensure that it is totally empty
  303. by removing any existing content in it"""
  304. if not os.path.exists(path):
  305. os.mkdir(path)
  306. else:
  307. for root, dirs, files in os.walk(path, topdown=False):
  308. if root.endswith("kernel_headers/"):
  309. # skip 'kernel_headers'
  310. continue
  311. for name in files:
  312. os.remove(os.path.join(root, name))
  313. for name in dirs:
  314. os.rmdir(os.path.join(root, name))