#!/usr/bin/env ruby

require 'lsmod'
require 'nm'
require 'getoptlong'

ksyms_file = '/proc/ksyms'
system_map = '/boot/System.map'
prof_shift = 2

opts = GetoptLong.new(
  [ "--ksyms", "-k", GetoptLong::REQUIRED_ARGUMENT],
  [ "--system-map", "-s", GetoptLong::REQUIRED_ARGUMENT],
  [ "--profile-shift", "-p", GetoptLong::REQUIRED_ARGUMENT]
  )

opts.each do |opt, arg|
  ksyms_file = arg.to_s if opt == "--ksyms"
  system_map = arg.to_s if opt == "--system-map"
  prof_shift = arg.to_i if opt == "--profile-shift"
end

all_modinfo = {}
vmlinux_syms = []

if FileTest.file? (ksyms_file)
  all_modinfo = Proc_Ksyms_Reader.All_KMod_Load_Info(ksyms_file)
end
if FileTest.file?(system_map)
  vmlinux_syms = NM_Reader.All_Syms_File(system_map)
end

regions = []

stext = 0
etext = 0
do_IRQ_start = 0
do_IRQ_end = 0

vmlinux_syms.each_index do |i|
  sym = vmlinux_syms[i]
  stext = sym.value if sym.name == '_stext'
  etext = sym.value if sym.name == '_etext'
  if sym.name == 'do_IRQ' && i != vmlinux_syms.length - 1
    do_IRQ_start = sym.value
    do_IRQ_end = vmlinux_syms[i+1].value - 1
  end
end

abort if do_IRQ_end*do_IRQ_start == 0 || do_IRQ_start >= do_IRQ_end

regions.push([stext, etext - stext])

all_modinfo.each_value do |modinfo|
  text_section = modinfo.get_section('.text')
  regions.push(text_section) if text_section != nil
end

regions.sort!{|x,y| x[0] <=> y[0]}

offset_parm = "region_offset=" + regions.collect {|x| x[0]}.join(",")
size_parm = "region_size=" + regions.collect {|x| x[1]}.join(",")
shift_parm = "region_shift=" + ([prof_shift]*regions.length).join(",")
do_IRQ_start_parm = "do_IRQ_start=" + do_IRQ_start.to_s
do_IRQ_end_parm = "do_IRQ_end=" + do_IRQ_end.to_s

comm_args =
[offset_parm,size_parm,shift_parm,do_IRQ_start_parm,do_IRQ_end_parm,*ARGV].join(" ")

puts (comm_args)

