Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.67 KB | None | 0 0
  1. -- change @binary_size to simulate a large executable
  2. declare @binary_size bigint = 128000
  3. declare @offset bigint = 40000
  4.  
  5. drop table #block_edges
  6. drop table #new_blocks
  7. drop table #new_bad
  8. drop table #blocks
  9. drop table #links
  10.  
  11. drop table #instrs
  12. drop table #components_to_merge
  13.  
  14. create table #instrs(
  15. id bigint primary key not null,
  16. [size] int not null,
  17. type varchar(1),
  18. block_id bigint,
  19. component_id bigint default 0,
  20. traced bit default 0,
  21. pred int default 0,
  22. succ int default 0
  23. )
  24.  
  25. -- links betweeen instructions
  26. create table #links(
  27. first bigint,
  28. second bigint
  29. )
  30.  
  31. -- basic blocks
  32. create table #blocks(
  33. id bigint primary key,
  34. component_id bigint default 0
  35. )
  36. create table #block_edges(
  37. first bigint,
  38. second bigint
  39. )
  40.  
  41. -- The following are work tables
  42.  
  43. -- newly discovered bad instructions
  44. create table #new_bad(
  45. addr bigint
  46. )
  47.  
  48. -- newly discovered instrctions that need to be added to basic blocks.
  49. create table #new_blocks(
  50. addr bigint,
  51. block_id bigint
  52. )
  53.  
  54. -- componenets that need to be merged
  55. create table #components_to_merge(
  56. component1 bigint,
  57. component2 bigint);
  58.  
  59. -- Create a simulated program ----------------------------------------------------
  60.  
  61. declare @end bigint = @offset + @binary_size
  62. while @offset < @end
  63. begin
  64.  
  65. insert into #instrs(id, [size], [type]) VALUES (1 + @offset, 1, 'l')
  66. insert into #links values (1 + @offset, 2 + @offset)
  67.  
  68. INSERT INTo #instrs(id, size, type) VALUES (2 + @offset, 1, 'l')
  69. insert into #links values (2 + @offset, 4 + @offset)
  70.  
  71. INSERT INTo #instrs(id, size, type) VALUES (3 + @offset, 1, 'C') -- Capital 'C' means this was called by someone.
  72. insert into #links values (3 + @offset, 4 + @offset)
  73.  
  74. INSERT INTo #instrs(id, size, type) VALUES (4 + @offset, 1, 'c')
  75. insert into #links values (4 + @offset, 5 + @offset)
  76. insert into #links values (4 + @offset, 6 + @offset)
  77.  
  78. INSERT INTo #instrs(id, size, type) VALUES (5 + @offset, 1, 'l')
  79. insert into #links values (5 + @offset, 6 + @offset)
  80.  
  81. INSERT INTo #instrs(id, size, type) VALUES (6 + @offset, 1, 'x')
  82. insert into #links values (6 + @offset, 2 + @offset)
  83. insert into #links values (6 + @offset, 7 + @offset)
  84.  
  85. INSERT INTo #instrs(id, size, type) VALUES (7 + @offset, 1, 'l')
  86. insert into #links values (7 + @offset, 8 + @offset)
  87.  
  88. INSERT INTo #instrs(id, size, type) VALUES (8 + @offset, 1, 'l')
  89. insert into #links values (8 + @offset, 9 + @offset)
  90.  
  91. INSERT INTo #instrs(id, size, type) VALUES (9 + @offset, 1, 'l')
  92. insert into #links values (9 + @offset, 10 + @offset)
  93.  
  94. INSERT INTo #instrs(id, size, type) VALUES (10 + @offset, 1, 'l')
  95.  
  96. set @offset = @offset + 20
  97.  
  98. end
  99.  
  100. -- Find transitive closure of bad instructions ------------------------
  101.  
  102. while 1=1 begin
  103.  
  104. delete from #new_bad
  105. insert into #new_bad
  106. select pred.id
  107. from #instrs item
  108. inner join #links on item.id = #links.second
  109. inner join #instrs pred on #links.first = pred.id
  110. where item.type = 'x' and pred.type <> 'x'
  111. insert into #new_bad
  112. select succ.id
  113. from #instrs item
  114. inner join #links on item.id = #links.first
  115. inner join #instrs succ on #links.second = succ.id
  116. where item.type = 'x' and succ.type <> 'x'
  117.  
  118. if (select count(*)from #new_bad) = 0 break
  119.  
  120. update a
  121. set type = 'x'
  122. from #instrs as a
  123. join #new_bad on a.id = #new_bad.addr
  124.  
  125. end
  126.  
  127. -- Compute all basic blocks -----------------------------------------------
  128.  
  129. -- count the # of predecessors and successors for each instr
  130. update instr
  131. set
  132. pred = coalesce(target.incoming, 0),
  133. succ = coalesce(target2.leaving, 0)
  134. from #instrs instr
  135. left join
  136. (select second as addr, count(first) incoming
  137. from #links
  138. group by second) as target
  139. on instr.id = target.addr
  140. left join
  141. (select first as addr, count(second) leaving
  142. from #links
  143. group by first)
  144. as target2
  145. on instr.id = target2.addr
  146.  
  147. update #instrs
  148. set block_id = id
  149.  
  150. while 1=1 begin
  151. -- find all instructions succ that have a signle predecessor pred
  152. -- such that pred has succ as its single successor and they
  153. -- are consecutive in memory.
  154.  
  155. delete from #new_blocks
  156. insert into #new_blocks
  157. select succ.id, pred.block_id
  158. from #links
  159. join #instrs pred on #links.first = pred.id
  160. join #instrs succ on #links.second = succ.id
  161. where pred.succ = 1 and succ.pred = 1 and
  162. pred.id + pred.size = succ.id and
  163. pred.block_id <> succ.block_id
  164.  
  165. if (select count (*) from #new_blocks) = 0
  166. break
  167.  
  168. update instr
  169. set block_id = b.block_id
  170. from #instrs instr
  171. join #new_blocks b on instr.id = b.addr
  172. end
  173.  
  174. -- Build global block graph: first vertices...
  175. delete from #blocks
  176. insert into #blocks
  177. select distinct block_id, block_id from #instrs
  178.  
  179. -- Compute all weakly connected components -------------------------------------------------
  180.  
  181. -- initialize components
  182. update #blocks
  183. set component_id = id
  184.  
  185. while 1=1 begin
  186.  
  187. -- Find all links that connect instructions that have different components
  188. delete from #components_to_merge
  189. insert into #components_to_merge
  190. select distinct t1.component_id c1, t2.component_id c2
  191. from #links
  192. join #blocks t1 on #links.first = t1.id
  193. join #blocks t2 on #links.second = t2.id
  194. where t1.component_id != t2.component_id
  195. -- ensure symmetricity (only for WCC, SCC should remove this)
  196. insert into #components_to_merge
  197. select component2, component1 from #components_to_merge;
  198.  
  199. if (select count(*) from #components_to_merge) = 0 break
  200.  
  201. update block
  202. set block.component_id = case when block.component_id < target then block.component_id else target end
  203. from #blocks block
  204. inner join
  205. (select
  206. b.component1 as source,
  207. min(b.component2) as [target]
  208. from #components_to_merge b
  209. group by b.component1) as new_components
  210. on block.component_id = new_components.source
  211. end
  212.  
  213.  
  214. select top 300 'I' as Instrs, * from #instrs
  215. select top 300 'L' as Links, * from #links
  216. select top 300 'B' as Blocks, * from #blocks
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement